From nobody Sun Feb 8 17:28:54 2026 Received: from mail-yw1-f170.google.com (mail-yw1-f170.google.com [209.85.128.170]) (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 D226B72612 for ; Fri, 24 Oct 2025 16:10:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761322207; cv=none; b=F3QVEzd8dIVOqMTX1vYLC1gB1/fhBBsXuJYiYnTlMKjfSERkkqSKp2VVUqlS4tvMt1sZytJnSKeOtBsWM8OctZQY+4twD/MzMOhiaLQVnPlq/Z8AnHB0HtAqRYAkQNaH5bUHmO7Uy5UWeV+UlLvJYmAtB6H+UxgqK4TyJh8duZk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761322207; c=relaxed/simple; bh=7Ctj7U8/5C4UX61ox/HAuuPfBskF5Q9DSmh/7EoeFe4=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=edvkq7oRh9kvPHPOHEA+20PbM99DTN6kLvkj+aTlV9wy2tIK93SKJDhCQ46Itg//chLpmZL5XXQ5jDpLWpSaYRM4SKtE5NZIc64G4/8OVG68cUftNjyxA90W+ODoiUkMYWmrLAUulWWI41SlrzkdH3vAr/KIyp+IWDiM148xX4E= 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=VEHDXw+h; arc=none smtp.client-ip=209.85.128.170 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="VEHDXw+h" Received: by mail-yw1-f170.google.com with SMTP id 00721157ae682-784826b775aso25853177b3.2 for ; Fri, 24 Oct 2025 09:10:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1761322205; x=1761927005; 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=2SbWqW9Qai+Lun71fJPV2ZvcU3Evl3TvbhEARlh+dkw=; b=VEHDXw+h95jrzqb+ExCf0AKQIjbTt3kIghTdCoQVAqWa7ZVG47WZ1wKafk0fxJbkBp DE8XdhmjYf+53q+hQLFBFkzTy/f7VdsX2b8JgcrsHlTavQZZWMyXiBl4BcEeXD+2Ke0F H5OKuQ49+RL8ahG+kvxvJYUm2J6Guw1cLldFLHkbmsB6ijQw8aUfp7BwsZ5D3kxNlpqT 3TsIzVCrbE4rq9xyxAB+PrEGy3stCbE9ONaiQkQgXiBu03TV/IIs3nmd5tTegDWyiMno 3zv5WFj8NEOrypTtDLPJq8zFH61VzGEjdPWV5S0dhT0gczHSF+1jY42Xfm2QWRkIpD0f d2Rw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1761322205; x=1761927005; 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=2SbWqW9Qai+Lun71fJPV2ZvcU3Evl3TvbhEARlh+dkw=; b=sbmB8gI7tZ27gjuqa359UwRMSG4/BGDAN8ssoNEGy/4CYoy3RNNxC/vXVY7sXDlmtG hck+8z4Ewc2lKf/w/Jf/pjcBYkU2oOCGz3DsqHyBadTNdCvequPVdS5x/YK55AyrTScM vf2RdIIKTE7/kI8ZmN1CeMfba0QcY0ESdcylr5Mo2cGWgYx1L5BtMx/aVB4wfqYNZ3+5 1smi2tjiPwxOORoGF6oPiwg9Xt3hvPvWJTtnXb7Xt+Bndrf8KXiJ8HtdPv3rSWOqu/Gr M2jJ9OLuKnbgb8sytOgDilGErM2ZqXivd3li2WY4MR6yrZ8dhTH51ath8Wsf/ahNBKQu mdyw== X-Forwarded-Encrypted: i=1; AJvYcCVGCz23HV3wS8nFy4bFc/6/8PI5BXJ1ch+U/BJ64uZElx9IHTsSQsacpdXF0Qw7eFoxnQPXOc15HUxJuNc=@vger.kernel.org X-Gm-Message-State: AOJu0Yxc7RAXy3w0EWnckPo7/M+r2MkMxX5TmOYMR2aH38e13A5pbtdH hCLNVuALGBXdMjmOhOfT2KzHSKEMucuUT1+Yy/KSX3zN+GNWnKXAgitNh1JWeDrt6wE= X-Gm-Gg: ASbGncueuhfApBbT+zlECfnTUQ9qRoW4DOkmmwUfKzi1k7UEgAE6aM/pAgxo0NtCJn4 by1utqJ81zkzFcvgYT9nc0zfwxYQDAO8Vo4fpzgWs1QWL8n0lvAxHMNFAH4CDo9etgrdjWo/CyV YGN5eUR7WzYFRziA9buQDHUbb1Xo4giNPTiZH+KT/JBORUk7LipjfFIy0Cz0qDFLlGgugGtjRkU HZ4Ff86cuP8lzzr55eqLt5Zd+AP8EFAkQLJPk2mdCAb5udYE7BPSvRo0cOZyMuElz5hFutydae1 Q+HZjUbzi4kFgL4BOsJzluSfVIjJ7nFn1RP5iWDVPrQXKaRoQCUg+2HLhi9c8rZZ9la0OtQI4mh 6tRjPA2ajM7yk/9fWCLFUMVc1z7xKasTLWqWdrukC2Up1/yDZ9i9FRYlBqL3Iz38U3GjUSqO6gt ey9pvYx+6fMH0R2bPHDZmRR/4DQWWuEhEK/hnLylntdiQUVc9oDnPDQXp7Ggp8qg0NLZ7jewCkm a3/dJZddt70aweQ+pN+zra/hUKeeAykJw== X-Google-Smtp-Source: AGHT+IHZAItAvq+Ap/Z72KhPLfQ8TowTJ5+sfBUaR7iDrNtO0b+4ThX0ZIHOf9SDvkQBFhT4ShLEEg== X-Received: by 2002:a05:690c:22c6:b0:784:8286:fde3 with SMTP id 00721157ae682-78482870f7emr209860417b3.42.1761322204728; Fri, 24 Oct 2025 09:10: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 00721157ae682-785cd6edd87sm14099197b3.51.2025.10.24.09.10.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Oct 2025 09:10: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 Subject: [PATCH v8 1/8] kho: allow to drive kho from within kernel Date: Fri, 24 Oct 2025 12:09:55 -0400 Message-ID: <20251024161002.747372-2-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.51.1.821.gb6fe4d2222-goog In-Reply-To: <20251024161002.747372-1-pasha.tatashin@soleen.com> References: <20251024161002.747372-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 kernel to drive finalize and abort without requiring triggers from the userspace. Signed-off-by: Pasha Tatashin Reviewed-by: Pratyush Yadav Reviewed-by: Mike Rapoport (Microsoft) --- include/linux/kexec_handover.h | 15 +++++++ kernel/kexec_handover.c | 75 +++++++++++++++++++++------------- 2 files changed, 61 insertions(+), 29 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 de4466b47455..6458f369a346 100644 --- a/kernel/kexec_handover.c +++ b/kernel/kexec_handover.c @@ -1087,7 +1087,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; @@ -1120,7 +1120,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; @@ -1163,12 +1183,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); @@ -1178,35 +1218,12 @@ static int kho_out_finalize_get(void *data, u64 *va= l) return 0; } =20 -static int kho_out_finalize_set(void *data, u64 _val) +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(); + return 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 kho_abort(); } =20 DEFINE_DEBUGFS_ATTRIBUTE(fops_kho_out_finalize, kho_out_finalize_get, --=20 2.51.1.821.gb6fe4d2222-goog From nobody Sun Feb 8 17:28:54 2026 Received: from mail-yw1-f181.google.com (mail-yw1-f181.google.com [209.85.128.181]) (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 5ED44333457 for ; Fri, 24 Oct 2025 16:10:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761322209; cv=none; b=rJPwPuyks7DDNV5eomYrhKupFQw2GrNgJeJ9rxdVfb42VptDOp0Ego+qwrAg6pPNaOlKu4fllZEL7+BQUxaDO37bXTBuvvCB0dbY5u29ywlJv+TiD3fc/27UgtigwzOGZpVSk9HYo3XXVQqSe3/6ADWZsUMwAXuIe8CljXhDEAg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761322209; c=relaxed/simple; bh=HpVnkUr09cUMeCvgZBnvfzeD6635psgAmp4EdWRvu8c=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gCCjkhXm/Wo3jmnIHCzmO5dSOgCz6229Zq8wcIUAsQZTIUQhg0hygoXv+5dsjFEnH2TMxGBFBBz2kwUXLeVAxBKKI249pTmrpHrw0ACRGEteJNl8gHOT46ajkmYmt1Kd6SgcH9Vu0YmUnsRNk6jkhWR/Bdv0gIorFR5a0OQcOz0= 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=TDyImv1y; arc=none smtp.client-ip=209.85.128.181 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="TDyImv1y" Received: by mail-yw1-f181.google.com with SMTP id 00721157ae682-781421f5be6so25758677b3.0 for ; Fri, 24 Oct 2025 09:10:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1761322206; x=1761927006; 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=xGi3YkJalT3Q1XsBDOyYfr2SHo9OSDS0oxxt0K7ji6k=; b=TDyImv1yakiuo7yVzRtXvHjglOIt7oPhkAhCW1l3XzYFfI2vSkgfhvZdUrAx9OJ+BI fReLM5l1wi+LdECRqgbxU9PeZigJDZFkfCEZkej4cCsp1pQQt/UPCa8h+N0vZ5RKcYwZ l0hnCX3C//Vbn2c8bFH1eGM4i1IejSUtBYO/BVkiS9NUN8c41Onsu9MQos30I31rCdxJ T2QF9+xIHU4DlGAuOJdL8EPSF7U1LvEHY+D7cf7pnLnwafnvqSl6K/Qp9gkiMDQQwUVX 9/hK1upKGfE5DJD/V5YBQBS+AoCMkI+v6mjoz0zS+7sfeEnwkvfmBPx9/HvOy3g4cCG9 Quiw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1761322206; x=1761927006; 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=xGi3YkJalT3Q1XsBDOyYfr2SHo9OSDS0oxxt0K7ji6k=; b=EJoflAXk6QemGiGz6FyKcx7Vpnj6Y2sHvVZSPsGGVubmCVU98GeQ3Tn6ROHTQPzupy qrNRTVGb8raImBfXfBIKQSzzhC0cE0oSEpBVpa2j15E3b8RR1qC8j/r4aEyfxDVvARjs I9aHjYXLFTygeUCHcjBBXh+Me8NG65q90psfbTPNBO/zrGG8Nad5EKfbc+DyRNaVYGdo iqTmu42G2IOzPKWx44DJlrzKHzyEoi420859LUych2g/9bwIS1aAT9Hzc5+KiF/pRLYm mRO/y6roQP9Qe89Am/usMXekL4COsrkMjfyz2nkI7JrXUv6dhBJ6aEsgu9JeCKIfh6LX zx2w== X-Forwarded-Encrypted: i=1; AJvYcCXxbvjhOMhvyU0IOMeYxmnHZlCK2M9T3XR0HWC3ohk+qiOXh/1TA3Xv8dxWGGD7XNbxWkHzJZZHU+ONAT0=@vger.kernel.org X-Gm-Message-State: AOJu0YxFMor2wJgb2xHLaGtCcgZUJXb2diwkqE6Pak5vRbm5pmigpt+E T5W/ydqOeqN/zABcSLrxj2JLOvfx1RjNViVVxVswDc8MK6Bj4KxpvxcplhkftSIvCHw= X-Gm-Gg: ASbGncvogC2Hx77waPHsGdv+o6rCw/09F/8Hp+XvwR0x5qlmC/LMe3Es7O3Gx8AqjSZ QYJ1cIn4edeqmflCOHn+By9WA+BoArQani46xarqQTa06hlDljvhl2ha59/3+Y2e9g/0VLhbF4q 3VT6UDy3glmEyPXZOvXBoWjctpLq5X//00UZHvNyb+djSsFfazeuVT6owR08iZMRhxF/KZYkE4Q OQqCPpvNUVxdMd3fx2ErHGnoApsMaBS+DjFKMZb5zbIvZ0JWWL+JZIa1svtXO828mQzOjy8rGXC e5iRxuNuHGqROptJkLALGZx53GDmoUqi3yVU1kLfaLRCIoZPJZinS0Tro80M1tCTNlR9vWU8bTz gn5vmk7hXLIogixgn8LxdNcN7udFrcgMk94SzikkpY/WZavbbfzmpFrDOxpiOI/pUJDA3WDdIZm SoI5uaEyBJxEkmw2NFUtMQO6P1G5VuYV3jZdASyxKVlihWFmREfiv2CuyFTXIed8KtAHlXvY0kd 9TPYjJGmGs2BKWo6zEBIs3R12h+OzqtEA== X-Google-Smtp-Source: AGHT+IGCBUncqFwdegj1nIKiQJ0zvGzhhfJ9Kfw5HDrBRalX9t1H7m201KO+uSq0bq9de190LiRlLQ== X-Received: by 2002:a05:690c:338b:b0:73c:d011:5769 with SMTP id 00721157ae682-785e02318fcmr25454717b3.52.1761322205946; Fri, 24 Oct 2025 09:10:05 -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 00721157ae682-785cd6edd87sm14099197b3.51.2025.10.24.09.10.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Oct 2025 09:10: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 Subject: [PATCH v8 2/8] kho: make debugfs interface optional Date: Fri, 24 Oct 2025 12:09:56 -0400 Message-ID: <20251024161002.747372-3-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.51.1.821.gb6fe4d2222-goog In-Reply-To: <20251024161002.747372-1-pasha.tatashin@soleen.com> References: <20251024161002.747372-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 Reviewed-by: Pratyush Yadav --- MAINTAINERS | 3 +- kernel/Kconfig.kexec | 10 ++ kernel/Makefile | 1 + kernel/kexec_handover.c | 226 +++----------------------- kernel/kexec_handover_debugfs.c | 216 ++++++++++++++++++++++++ kernel/kexec_handover_internal.h | 37 +++++ tools/testing/selftests/kho/vmtest.sh | 1 + 7 files changed, 286 insertions(+), 208 deletions(-) create mode 100644 kernel/kexec_handover_debugfs.c diff --git a/MAINTAINERS b/MAINTAINERS index 5ea78444f035..35d7942b2082 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13815,13 +13815,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 c94d36b5fcd9..9308a0fb1419 100644 --- a/kernel/Kconfig.kexec +++ b/kernel/Kconfig.kexec @@ -118,6 +118,16 @@ config KEXEC_HANDOVER_DEBUG scenarios and the extra code might be adding overhead it is only optionally 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 9fe722305c9b..2cf7909a74e5 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -84,6 +84,7 @@ 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_DEBUG) +=3D kexec_handover_debug.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 6458f369a346..da071277d85e 100644 --- a/kernel/kexec_handover.c +++ b/kernel/kexec_handover.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -30,6 +29,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" @@ -105,8 +105,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; @@ -114,20 +112,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), }, @@ -477,8 +471,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 @@ -674,37 +668,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. @@ -716,7 +679,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 */ @@ -733,7 +697,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 @@ -1064,29 +1028,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; @@ -1136,8 +1077,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) @@ -1206,92 +1148,23 @@ int kho_finalize(void) =20 kho_out.finalized =3D true; =20 - return kho_out_update_debugfs_fdt(); + return kho_debugfs_fdt_add(&kho_out.dbg, "fdt", + page_to_virt(kho_out.ser.fdt), true); } =20 -static int kho_out_finalize_get(void *data, u64 *val) +bool kho_finalized(void) { - 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) -{ - if (val) - return kho_finalize(); - else - return 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; -} -DEFINE_SHOW_ATTRIBUTE(scratch_len); - -static __init int kho_out_debugfs_init(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) @@ -1355,56 +1228,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; @@ -1419,27 +1242,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..a91b279f1b23 --- /dev/null +++ b/kernel/kexec_handover_debugfs.c @@ -0,0 +1,216 @@ +// 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) +{ + if (val) + return kho_finalize(); + else + return 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 index 05e9720ba7b9..28c0e971613d 100644 --- a/kernel/kexec_handover_internal.h +++ b/kernel/kexec_handover_internal.h @@ -2,8 +2,45 @@ #ifndef LINUX_KEXEC_HANDOVER_INTERNAL_H #define LINUX_KEXEC_HANDOVER_INTERNAL_H =20 +#include +#include #include =20 +#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 */ + #ifdef CONFIG_KEXEC_HANDOVER_DEBUG bool kho_scratch_overlap(phys_addr_t phys, size_t size); #else 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" <; Fri, 24 Oct 2025 16:10:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761322211; cv=none; b=qazq0VKibJu8w1o34LHxCgbwSI2Lf4L+YAu9/tvUt86q8o6mXp/IXOg7xH94sjTRxe9iUitF3/G5LgtmnCGOyXUsHo96aUmiEZWB2IH/nw/Tjlq6xZcTdMJI6eOSUnXkLXiQV7a36LcpYNZXj0NpjIaCc4qNp5vyDT2J1Ex9uI8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761322211; c=relaxed/simple; bh=6VywHE2AGjGSSVyPJ6R8SixgQoK4lGivHHOiQpBpcBA=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Dm6uVbkqoOJAQcoY39BtPaBIM5SesbMhquwdfOitp3IgVKFmo9Wd0hibc3JADipzCljhZujEIT8DBmLq5x3JcZK2dais1Qj9NMkX4S5Wp0YcVELeqSDcrHoU6AaTvozzn4GG/i2/9jsMb0VnAV7VhwLYHAkEHoqeu2o2c9VBLb8= 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=Lc0Y9Dqi; arc=none smtp.client-ip=209.85.128.174 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="Lc0Y9Dqi" Received: by mail-yw1-f174.google.com with SMTP id 00721157ae682-78356c816fdso23921817b3.3 for ; Fri, 24 Oct 2025 09:10:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1761322208; x=1761927008; 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=r5FY4TtL84bBCvkNwXKdclYeCL27GGb/qseSZpuF5vg=; b=Lc0Y9DqijohoUAUVCDVAGe1bFT5AyqlD2F3uPEVS/+cQrh4uTd59LrhY5rPXeWAB0l KQhc1WMOtgPZG0KGi1oraMKUrqWSCDDUHZ3KSX5SRFwNSVJ2lKSLiyvCByneKFNCWmGJ ow10SDBoywNn33b4DsQ3N121qZ3XHn90HjEZKB5nojVyZizrGOq6Ms6d5+lIfdh7yVc8 wgjIgQmgQMBj/uTMmjH4DoIg6zcvIuVUAVfspcgux3MLmTRUyMWrUEJP4cMAkg7+QFSz iqdo4QTh3DugkidIE1cbUpFxSdHSJOJe5KcSGV2hPc2P3iEDADOX6fiIlw2x62/SNh2t MPLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1761322208; x=1761927008; 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=r5FY4TtL84bBCvkNwXKdclYeCL27GGb/qseSZpuF5vg=; b=QlpsJ9g8bHPXFVmJCpMzDezzd2+lYk7mQBIIRxw8dkkxqPsdQrcTqqN3FFInK15SGk pE+Km5oyQ7xBbp4xgUOZYa4ol2SG4SSfasM42IV34MDwMeHH7RrSUjwEDy3My1QOpUzO 3b85vR2k6rCEhHD48XdbQF4UzLgOfjbjYBojDk3gSCyorLRZSLFShJyvdoGina6fFfTU GE7CPjhgecMJKExdJlBK38MHJs2Z/kNVLKhw49BGIM7xcKILEEfKiZ1TDq1acmfmL6FB xt1NANdxUKgoGnKMzPD2rsUROqNZAX6QRISUBpUCQ1vXH5NM5Ofx7l/vFDKVj8z6aBzz B09Q== X-Forwarded-Encrypted: i=1; AJvYcCVoJZy24GWaz189asm45C/l+EaMUG32G226nvqd8Rf0CRMVdvJpjoe8Qdh8GG7twufaY7spbrbe2ZLymi4=@vger.kernel.org X-Gm-Message-State: AOJu0YyUZMR6NSv8cvsbUl+ZIjY8245vN+qtAg64cP3Z1SPQcuRJJmAg HIEW+iUJ1tnSUfQZu6BfRK0RhQljmSRjDgNF9kjiK7CvIrCRQnnwVyOoZDzs33h7plI= X-Gm-Gg: ASbGncsDX9/3UlhdQTQ46rny0g4Eo09yjQOJ50DbWo3vwAQfRuH0+OJmUkQOFpRpbe8 JzbGlshND7Hc0YJXLJko7oN1MTImRk1KBO8EJR7MUsfMCFmKP4SRIkq8AzIC9MGFmrBFtvWQm/f t6FEbNHAUj43btvW4cgcPT0QQ6qbimPHYU+FIB3Y+LEDxPiFP6Ap79wTBmKR1DKOz/d/+rSKmzO J0DIVcr5DVvABOohGsVDMTUYwbTFWPXYJcRhFtQUqRBVQihhefkJ3J11SubkiuabxXulzk2SoBN sdd8BNCF2TcEdJBA7fHE+WTVpVbKUvgRPaZYDhAsTYx1cvIQNRMtMUCsXt7RXXA9UJUZ+nwBbkN HmLraOOxDh15sxMMtEKU1ZtiFHALrm9NsdGZ7bij2oCpQpBydgZNMxqqIqw+p+YkMV5HiRw8RDd Tt6TiSE5nRCnyL/39DjNT2c3MpZJfLr73w+sD8qR8FSo3GSNsT0w5gn+hOP27XzJ1BpqXaJgyw4 kwr5VFgK38KfKOc41oUGvM= X-Google-Smtp-Source: AGHT+IEXA4oL0aDffbC7BgvPzu2HIytLfA9DEVBx9oM2AIksawh83BaCGPxJdsBeIYPRaZpSuU6+Ow== X-Received: by 2002:a05:690c:4981:b0:784:a232:b3d9 with SMTP id 00721157ae682-784a232b466mr153539257b3.18.1761322207439; Fri, 24 Oct 2025 09:10: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 00721157ae682-785cd6edd87sm14099197b3.51.2025.10.24.09.10.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Oct 2025 09:10: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 Subject: [PATCH v8 3/8] kho: drop notifiers Date: Fri, 24 Oct 2025 12:09:57 -0400 Message-ID: <20251024161002.747372-4-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.51.1.821.gb6fe4d2222-goog In-Reply-To: <20251024161002.747372-1-pasha.tatashin@soleen.com> References: <20251024161002.747372-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 Reviewed-by: Pratyush Yadav --- include/linux/kexec_handover.h | 28 +----- kernel/kexec_handover.c | 166 +++++++++++++++++-------------- kernel/kexec_handover_debugfs.c | 17 ++-- kernel/kexec_handover_internal.h | 5 +- lib/test_kho.c | 33 +----- mm/memblock.c | 62 +++--------- 6 files changed, 126 insertions(+), 185 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 da071277d85e..82137eba1474 100644 --- a/kernel/kexec_handover.c +++ b/kernel/kexec_handover.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include =20 @@ -103,29 +102,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 @@ -369,7 +373,7 @@ static void kho_mem_ser_free(struct khoser_mem_chunk *f= irst_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; @@ -377,7 +381,7 @@ static int kho_mem_serialize(struct kho_serialization *= ser) unsigned long order; int err =3D -ENOMEM; =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 @@ -409,7 +413,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 @@ -670,7 +674,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. * @@ -684,34 +687,41 @@ 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; =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); -} -EXPORT_SYMBOL_GPL(kho_add_subtree); + guard(mutex)(&kho_out.fdts_lock); + list_add_tail(&sub_fdt->l, &kho_out.sub_fdts); + WARN_ON_ONCE(kho_debugfs_fdt_add(&kho_out.dbg, name, fdt, false)); =20 -int register_kho_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_register(&kho_out.chain_head, nb); + return 0; } -EXPORT_SYMBOL_GPL(register_kho_notifier); +EXPORT_SYMBOL_GPL(kho_add_subtree); =20 -int unregister_kho_notifier(struct notifier_block *nb) +void kho_remove_subtree(void *fdt) { - return blocking_notifier_chain_unregister(&kho_out.chain_head, nb); + struct kho_sub_fdt *sub_fdt; + + guard(mutex)(&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; + } + } } -EXPORT_SYMBOL_GPL(unregister_kho_notifier); +EXPORT_SYMBOL_GPL(kho_remove_subtree); =20 /** * kho_preserve_folio - preserve a folio across kexec. @@ -726,7 +736,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 if (WARN_ON(kho_scratch_overlap(pfn << PAGE_SHIFT, PAGE_SIZE << order))) return -EINVAL; @@ -747,7 +757,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; @@ -848,7 +858,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); @@ -1030,11 +1040,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 @@ -1044,17 +1054,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 @@ -1077,7 +1083,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; } @@ -1086,41 +1093,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) { @@ -1148,8 +1160,10 @@ int kho_finalize(void) =20 kho_out.finalized =3D true; =20 - return kho_debugfs_fdt_add(&kho_out.dbg, "fdt", - page_to_virt(kho_out.ser.fdt), true); + WARN_ON_ONCE(kho_debugfs_fdt_add(&kho_out.dbg, "fdt", + kho_out.fdt, true)); + + return 0; } =20 bool kho_finalized(void) @@ -1232,15 +1246,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) @@ -1268,8 +1284,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); @@ -1280,7 +1296,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) { @@ -1416,7 +1432,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 a91b279f1b23..46e9e6c0791f 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 28c0e971613d..17ae101dc6ae 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 #ifdef CONFIG_KEXEC_HANDOVER_DEBUG diff --git a/lib/test_kho.c b/lib/test_kho.c index 60cd899ea745..1c6c4ce83666 100644 --- a/lib/test_kho.c +++ b/lib/test_kho.c @@ -39,33 +39,6 @@ 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) -{ - struct kho_test_state *state =3D &kho_test_state; - struct kho_serialization *ser =3D v; - int err =3D 0; - - 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)); - - return err ? NOTIFY_BAD : NOTIFY_DONE; -} - -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; @@ -120,6 +93,7 @@ static int kho_test_prepare_fdt(struct kho_test_state *s= tate) =20 fdt =3D folio_address(state->fdt); =20 + err |=3D kho_preserve_folio(state->fdt); err |=3D fdt_create(fdt, fdt_size); err |=3D fdt_finish_reservemap(fdt); =20 @@ -131,6 +105,7 @@ static int kho_test_prepare_fdt(struct kho_test_state *= state) =20 err |=3D fdt_finish(fdt); =20 + err =3D kho_add_subtree(KHO_TEST_FDT, folio_address(state->fdt)); if (err) folio_put(state->fdt); =20 @@ -203,7 +178,7 @@ static int kho_test_save(void) if (err) goto err_free_folios; =20 - err =3D register_kho_notifier(&kho_test_nb); + err =3D kho_add_subtree(KHO_TEST_FDT, folio_address(state->fdt)); if (err) goto err_free_fdt; =20 @@ -326,7 +301,7 @@ static void kho_test_cleanup(void) =20 static void __exit kho_test_exit(void) { - unregister_kho_notifier(&kho_test_nb); + kho_remove_subtree(folio_address(kho_test_state.fdt)); 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.1.821.gb6fe4d2222-goog From nobody Sun Feb 8 17:28:54 2026 Received: from mail-yw1-f174.google.com (mail-yw1-f174.google.com [209.85.128.174]) (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 C6DA83375A0 for ; Fri, 24 Oct 2025 16:10:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761322211; cv=none; b=sVTu3a6RoP0EHSZ2hTIr9kTZk7wGUQHwYlwmGojeuAHtX5YP/kg0FcFF6T2IrxRuXuWME/yv3XFrezlQcURwRYcyGMBC7C2H+f65v59wwcO/QO+38vpKIJ0rGeWkct5d6gu6Ph+2Iz/OawwmMlFVS9ZGwDX8w+ERw+hf6/JBa28= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761322211; c=relaxed/simple; bh=YWFg/uFSNJCNeAz1R08CPTi95zQcLFxIUIFTBMGCGzQ=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XNGyBLDUtu5xf+tWndF5Khi7CfC6bvE3U/Xi1umihB/U6Pugi3cHFnvP1Uv/uHzYTx4Cssw1iecyVEgUeFf/vPO0ErGU8g9hFDyF9oL49i8eiCFPkTihy/ulAlKe4r1ZCreGYB9sSkat6nq99R5do4Frhzw7E1GEyNj80N13+dw= 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=VsXSr9Yj; arc=none smtp.client-ip=209.85.128.174 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="VsXSr9Yj" Received: by mail-yw1-f174.google.com with SMTP id 00721157ae682-7815092cd0bso27090067b3.2 for ; Fri, 24 Oct 2025 09:10:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1761322209; x=1761927009; 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=wl2EF5uWhoTCG3S4g09Ne4AB8gBDQLqMsfh4TvH+1zA=; b=VsXSr9YjBn5SugJ1H2WAPxlah7SgnvQho/Tl4TTKSmTKztFzZg7L8oSPI74df9rakD oaHja1ZM9Lbzl7nedpKdfA+fwGwAsJd87HobSrBYfzzN91FEqb02F7htVh+OkIaVPM5u fCCU+Zi6QxBsz+FdvQNIlAwMK5BuYWMlWJaxLuA93O6jbvBMVmxSVcmwkbPfQa7Hyjei PJlAJXhKHz4WYA1Q4vbWrnrh3109ASiTQH/o5V9YTDCzsfIa4phBXnsgzCxzRNyjsh6c 5CtPr0MfyH6ABBUEL5IhKE9o6oSkDa/T2fjVLJ1sWidXBwXbED1rkZt5Ro3BmASz9AvC bYAQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1761322209; x=1761927009; 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=wl2EF5uWhoTCG3S4g09Ne4AB8gBDQLqMsfh4TvH+1zA=; b=YUNz9b4Z1xF7zayAuPDa2HBZ3ywTzZmgHp8dvMjeDbl5ujUCtF9q+OjBPVY5MzY7Ih A8KTbE8XlkkRcLGkyrePo5EDENrO3Ofnj8l/2f9UnTSFE8MC2pDcBxRP8Ihev5t4J8xf pU6+a02rMNcwVWWWkVXsZtjZCv2wRo5wPcDAN+P9K2dgE9Av+8jFm5F4cDgJzL3Pbzbh wW6aHak0YEab0hKmLXmHnje146iEOKudUL43BAKU9yIM8avkS4mWkCLs65pmLfl2xJ9t A+qRqg2y3zydViyh1U+Tfuc9YH1SANKAT5/8FkQ1JTLlkU23+csD90T4ZU69yBPAMY93 qaAg== X-Forwarded-Encrypted: i=1; AJvYcCXQlkrqdaMp54iiVXX9mjREn9c+rsS8Da+4QOPLeS7VxskjXfSPgNWoWfMvJ/Q2VhLPzj/e59UDxB/1uKg=@vger.kernel.org X-Gm-Message-State: AOJu0YxTOUzdmqQq+/0glNZ7H/UfBjXkUZ6BZwJyhjvnGTUZEPev3JUA SNVW26Dm2GotT1pUajwKaNk4+mf6cF6caR2Us3FIrsgu7H/GBiryIzB4ott/jgoZTL7Skjd+mOd M7CEY X-Gm-Gg: ASbGncsAhE79Y5Q64f+2Wdh7ygpuHPonIYonFGdv6VQc8MbK5j9T9b/RvFpqbY5iy++ AcCIZBdEOF2+hAIuRQFshCjkkaq7Et+3VnZni1Rd01Et8pJ+JzGLNiflLzxreAD77aDzm5w1Qsb Gct9PCtP9tfArT0KkyF7bZMmebGQV2GhJjoJfAQgUJ/M1NAQb/ECWxMdZ+MnsRElByH4oOMRxVu fBfNbxZlnAqBP438MtkslIe59Nonx41YVQN/2/f93zwc6f2YW99704q01nW5q7xq+e94EOEUGrf FgCj4zSLCqnTaW4M0ZP5xcm/SPJPlC3IgYrlee2a6d8UZFGXk7bMLZX62g6MBXNnZF80MI3RatQ kRooNvRz/EsxNgAnuHu3I9quq1NZfo4GSPVEkYvpUM+HZ6a2mYl+HCoXEFlvl3Vd8LBb4qxjZ2o oouKWNWaXTCbmcOcWqUPZzsUU/6xJ86c7fdZBqWFs0uQq92NQD8jVJFQpNgY5IAjcuYDnFr6ugv K4mnB5YiB9KufSqD8wB6aOa7LAfA0vFEw== X-Google-Smtp-Source: AGHT+IEOPbBvm+lExMBK1VGNT5FBczDOJCWJOjmYu7xROX/4TrUbJOB5wagHwsMhLi4jdkRspXck2w== X-Received: by 2002:a05:690c:4b13:b0:783:7266:58ee with SMTP id 00721157ae682-78372666210mr456748687b3.7.1761322208709; Fri, 24 Oct 2025 09:10: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 00721157ae682-785cd6edd87sm14099197b3.51.2025.10.24.09.10.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Oct 2025 09:10: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 Subject: [PATCH v8 4/8] kho: add interfaces to unpreserve folios and page ranges Date: Fri, 24 Oct 2025 12:09:58 -0400 Message-ID: <20251024161002.747372-5-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.51.1.821.gb6fe4d2222-goog In-Reply-To: <20251024161002.747372-1-pasha.tatashin@soleen.com> References: <20251024161002.747372-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 Reviewed-by: Pratyush Yadav Reviewed-by: Mike Rapoport (Microsoft) --- include/linux/kexec_handover.h | 12 +++++ kernel/kexec_handover.c | 84 ++++++++++++++++++++++++++++------ 2 files changed, 83 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 82137eba1474..994ee0b70757 100644 --- a/kernel/kexec_handover.c +++ b/kernel/kexec_handover.c @@ -157,26 +157,33 @@ static void *xa_load_or_alloc(struct xarray *xa, unsi= gned long index) return no_free_ptr(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; } @@ -745,6 +752,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. @@ -789,6 +820,33 @@ 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 contiguous pages starting from @p= age. + * This must be called with the same @page and @nr_pages as the correspond= ing + * kho_preserve_pages() call. Unpreserving arbitrary sub-ranges of larger + * preserved blocks 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.1.821.gb6fe4d2222-goog From nobody Sun Feb 8 17:28:54 2026 Received: from mail-yx1-f47.google.com (mail-yx1-f47.google.com [74.125.224.47]) (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 AF1E43376B9 for ; Fri, 24 Oct 2025 16:10:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.224.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761322214; cv=none; b=Cf3Q6KOX8VgdtKAwnLO36RFad8HX8Z3q0BfgGBO0IISWkbXVfadpjGcPHvLRF+7h/5ZrkRnfz8VfEPPUxXpR2ZOv/Uvwa0pqqAn71jbOcc2srQa27GasTxdV5vsFwy+GwTnJBrr2t1Ys1oUYjQ063o+ifX5ZY9hJw1+UurNCSOM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761322214; c=relaxed/simple; bh=Qk9S6IHmnrfw6wGq0UeG8nzAs7ZVD29vG6VZbpdt4P4=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HoaDqiBEgcXMEdRtIX3SAxms7bNjR4pQmpbTFDb2uSQXxi/Lx9C+cSCXCpIc2q2MDdBK7xgn4dzl/Rj4BUa7Iwehq2aKbWcnc0b6+7t071oGovwyAaVPGm9t9j5RtcMKd9NekNL9z717q7NTr0UE77orO8eCaE1O/q1DWF46eRc= 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=i8TI6USH; arc=none smtp.client-ip=74.125.224.47 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="i8TI6USH" Received: by mail-yx1-f47.google.com with SMTP id 956f58d0204a3-63e1e1bf882so2168840d50.1 for ; Fri, 24 Oct 2025 09:10:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1761322211; x=1761927011; 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=tqVXyF+IsYXkvSZaiTZ7JkU0PjsMFTNFd+jvNj7uHBc=; b=i8TI6USH3ovpUOvOqT7ES6/CEvz+kW1mdR/tOkbCef1KYO1Ff6QgleqdhlUOEcCBD9 j0LL/Ir4RyOT81WiLI2jx5dXHieXzlYwfYYWiqbFKn+CcKPgAg1rJUKFkRpjsNksawQc gBU54fw24tRt3r3/7IJ4MWPzBj3T0edqKPIszJfTt3Ok8Im3IhvW0TH9HtvIqF1AL4rb 0ChP1HWn6zETm5al/KiNgYE640m+17VmjkxYfv066qEJZree67E1oYk0Dxg77TAEJVlw GQ1RMsiaKqzK+YyoMDPpC7JiirTvQ3+3cRFaYvAOUs1obbAJKitVlhfV6Am4x54Jt9HP 0mvg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1761322211; x=1761927011; 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=tqVXyF+IsYXkvSZaiTZ7JkU0PjsMFTNFd+jvNj7uHBc=; b=sqIiNbGUUxzM063pX5iDOJMa4lnyH5Ag8jHmZED82MlS/CyWA21xq92zvJYmuu5D7T YxSGIvQ1uo5qOg9cqhxlf15TkID/q56ufjolIUxomq32CjwXUWiYwko5KhgOS5x9FGHH ngIfRdB6bYQfOYBFhpHWzTbK7u3xGx2H/XQBP8rqZkGovc9KwyB8IQR2WAtcybOw9JUY yNPwa0n00sbfbIrDIPJoEwq9Me3B1r+8Fl7b+LlcstbjglP/eNTizcuBouRax+dV++xW TbBOmYmpH8lGB9qif9B40Sx4CIezRP8CSzSD3XeHS6uSUVAwkDFeHZEXHnO3nRp8m5Fl W3Hg== X-Forwarded-Encrypted: i=1; AJvYcCW3Gym0pQCpyftacWaLCMkx2aaFK74RkYplTPiQRznvpDo+tkTpzG9vljZOwa//Dcxsl5GPL7deT2UCDl0=@vger.kernel.org X-Gm-Message-State: AOJu0Yygdips8fYQhBpTTZ9Zje9/mwgW1gJ7AYpNy0C7rOTOT+C/LPu0 1CYaRyv3Yw2aIX0/5uV6bFT1WyBRPbqfp1V0VW1cGCPIrjMsNUgfBMcBxhv2/3jcMpA= X-Gm-Gg: ASbGnctNoWX5NkigprG79LBvvKn85qXeVOi5gnYTCave2g48iiLYk2t9iLycbfANRmv iZNz39bkAcWj9YkCcaqK6bjz2sgfXP2yX84GsRtZfxAejGCUTkX+FPa9/MKjMTwBqasDYHesm/q Hg/R4a77wGf0cqqCMDkEE6X9tzDC8HK9o5FQpuc2NoDkvxhDcdfbFWMmM36GCMIK9/eNXfe5Lf2 h/FgD8wrTau+0y9zqf3mAclLg4bHggi8fXfzZJHaFHAaZMyLT7mXlefImM02N9DJWVgXCFanDCY 54UtOfyPBIgeI7AytJaTFo5ns0OPe4iLAGuGSs8G6HNod7+9Gfu+WyJDV4fnVLoZfJRwyUCEw7M DWjHU/XCqN63kUyyj/04pat0GxxkzjYVrvustpoiA4QT2CQqY5DYmBlQt5eogEyOKwoGaMrUfwt yu3kTD0V2x312IlK2xPgiwsF0M/PKE/UC6u69iC3G7kdPLBlvBGLmqbkiBi72TDecZoWYJIEPSY vMMBwFIr7dC4Uu2CKXQZsLy45wvPckIRQ== X-Google-Smtp-Source: AGHT+IE1Y1ssC3vDPwXKD9Vohv1X1EAngxcUz/MZcTAaLZ2Xt65ito/oPm7FTBXTLQh5v9nY6sOF/g== X-Received: by 2002:a05:690c:4991:b0:784:8994:298c with SMTP id 00721157ae682-78489942dc2mr350965587b3.28.1761322209785; Fri, 24 Oct 2025 09:10: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 00721157ae682-785cd6edd87sm14099197b3.51.2025.10.24.09.10.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Oct 2025 09:10:09 -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 Subject: [PATCH v8 5/8] kho: don't unpreserve memory during abort Date: Fri, 24 Oct 2025 12:09:59 -0400 Message-ID: <20251024161002.747372-6-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.51.1.821.gb6fe4d2222-goog In-Reply-To: <20251024161002.747372-1-pasha.tatashin@soleen.com> References: <20251024161002.747372-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 Reviewed-by: Pratyush Yadav --- 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 994ee0b70757..6aa25d304bad 100644 --- a/kernel/kexec_handover.c +++ b/kernel/kexec_handover.c @@ -1098,31 +1098,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.1.821.gb6fe4d2222-goog From nobody Sun Feb 8 17:28:54 2026 Received: from mail-yw1-f169.google.com (mail-yw1-f169.google.com [209.85.128.169]) (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 C9D5F3375A3 for ; Fri, 24 Oct 2025 16:10:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761322213; cv=none; b=Z+p5Vg2KQCc6MGczX1YIIDS3YhNlEKK2PCB7A8+LzVmVq0o28xErfwty0U7l9M1WtdQcKzpy3Y8OK0QvYZ/Y9SVh4th7k6OsP75ynZMNrP8WPTxXzh+8pVy0mxgoBOiH8dUFIUDFAdmf0hYBic/Ka9ybJcg82ldj1w0QsC/ngtA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761322213; c=relaxed/simple; bh=q4+9pj1LZkPHVsjDnnJgCMXpKmubt7lvzC50ITZTU3k=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JtrgyhZEvhU01CUTd/dfCd3rTcvaCEpmJJjRK0MbvOtYo1Rpn8F/xPglOXTHbGYoFJVEvYQzYE/bTaVTN4ZSjTyZ1N8G1RSLbwyfpr2CvGh6vNFK7LPynKAppNVYeHXxoEMGl+GS1NV3wU4ZI1BbM3LXvEgkGYuZMt1Jt5rH6uY= 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=bCv0CBFE; arc=none smtp.client-ip=209.85.128.169 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="bCv0CBFE" Received: by mail-yw1-f169.google.com with SMTP id 00721157ae682-785db6b7484so11314397b3.1 for ; Fri, 24 Oct 2025 09:10:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1761322211; x=1761927011; 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=sN3NXoZOBQaV0qk4GQkx+g1ZE3W0dyobKn95aWS8UQY=; b=bCv0CBFEWxh4vaJQrFBxMZVOqjISjA5+mpNAMUt6rdVsY/VGRkwAUqUt222Y1bE/Fy 82ICQukormfU4kBQw7Yy/bmJjah+yJOQszVSDfFtsonbakcItmwXUs+ND+kAxNSiGZY6 P/8svyI+Quwn8JOFfK18PD9GiTz9jBlHcofDvSHEBke/LioOfQLBCjpbifd640Bejokx MORLhRMZ7zc2TnO8RpgftWpcnABGKZvFejyZHfDWzfBi/jEtaFgQqRPEVuOVCzZ5ZdC3 wCyVkj1qEiBj9p7ZyafJwF6qrySUBE+AxM0SVmmD+ixl5E/xs1m8syWZsEaQIzbRISJc eWZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1761322211; x=1761927011; 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=sN3NXoZOBQaV0qk4GQkx+g1ZE3W0dyobKn95aWS8UQY=; b=ujCvyYiSyVoFY+KLj3qSddo0MeW+CZBAsiF/Wuk4EABsdbgpaM64hne+xN7T05gR1Q d7F2IMJBDeyj3kbsmkSikzT1W3H4BZQ1qZd5JFEDhQkipxAgknDNpCAiD2GKpFi0fcUh 3NqkyjaY3MtrZhGEMMgM5ysoZp8zfhQBlvCJh6Mrxgc6EQLyzOvJbtvw5U87742bHpQn Xzzs4rA7pcdARC9jV2Ru4Zv98OI8MtfOt1c9I9vmuyKVNZrWTw/McV9FwVadPnT4IDv6 LwJu0mNydVq+8zV2zmHls/lgBEWCZG8sC2JMSC/zMTILmjf4PqjOvBaGWXXoN23tHioh X4yg== X-Forwarded-Encrypted: i=1; AJvYcCW/dKsFNcycgxYMTtLY8hmorSTeFGOoiCQwyjR14xiWLedeK23cMFXOORKlxC8joStzAXWeARXyOw86KbY=@vger.kernel.org X-Gm-Message-State: AOJu0YxnF6Gv9N7r7lJtKI2sCyVJe5kXNwIEttsuu4xHKIGzTWHFw07O greZEj90hrmFfkyivnv/UjKNDIm9feqM8BoWW2D3Z+RoZoqCgaHdZ8kZeei/LqkgMgk= X-Gm-Gg: ASbGncufBG9kDLZhy6CcpJoWe0kzbZt+4I9129sHz+8PC/X86+SLwsY7OUvuFt2xqX5 7YOkYEdnlvmoC2S+4glLrh+d4lTN1/gfxWN+P5etebIx+UgaLvEGHL1yyFf2l31n9bEnKhI/3R+ qTzErTR8XvAH2DN04KJsq0Lh8harm2157wgLDXuhyAVIsBno7nB4uBr/yPyZqucv2g/GsWdTTV4 kwbv/WKL314bbALkz8lOLWaoNJzwJxglxJtZ+64vbg++Dmuzil6fXxbVrQ86ifROl20CJ+5sGcV jSW5P8ssfpaD+53aqbQJNWBArEp2u+sjVYakVjSks+KZNyK8/rV/a+rIF3awjEk4UOwQaCuJG/e D6+emA/asmcFTihQW62J6BDcuMNF5aYuMsCx+39rSas2VBNTjFxpwms1LMDb+Mmy6fLoCl/WIT8 s0y1mQWIc0ogFKgkCdlYOPwNMTR2CaGWeDEW06rKEfiskK6o86wUXFjr5STBk0A2moOm8IlQFdu JYw65PkBVG3HYEb5EIOSIumLRXCeRIVvQ== X-Google-Smtp-Source: AGHT+IE2zX+p6Y3PDMVI3Fio8m3zVktQ5V7vVyOcKDfiGfYYf436D7pO0NOBbSVmVxYTK4k34aoLiQ== X-Received: by 2002:a05:690c:4a06:b0:785:cf36:6b72 with SMTP id 00721157ae682-785cf366ba7mr65136627b3.50.1761322210780; Fri, 24 Oct 2025 09:10: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 00721157ae682-785cd6edd87sm14099197b3.51.2025.10.24.09.10.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Oct 2025 09:10: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 Subject: [PATCH v8 6/8] liveupdate: kho: move to kernel/liveupdate Date: Fri, 24 Oct 2025 12:10:00 -0400 Message-ID: <20251024161002.747372-7-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.51.1.821.gb6fe4d2222-goog In-Reply-To: <20251024161002.747372-1-pasha.tatashin@soleen.com> References: <20251024161002.747372-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 | 34 ---------------- kernel/Makefile | 4 +- kernel/liveupdate/Kconfig | 39 +++++++++++++++++++ kernel/liveupdate/Makefile | 5 +++ kernel/{ =3D> liveupdate}/kexec_handover.c | 4 +- .../{ =3D> liveupdate}/kexec_handover_debug.c | 0 .../{ =3D> liveupdate}/kexec_handover_debugfs.c | 0 .../kexec_handover_internal.h | 0 11 files changed, 51 insertions(+), 41 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_debug.c (100%) 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 35d7942b2082..400209b74d95 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13822,7 +13822,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 9308a0fb1419..15632358bcf7 100644 --- a/kernel/Kconfig.kexec +++ b/kernel/Kconfig.kexec @@ -94,40 +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_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. - -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 2cf7909a74e5..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,9 +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_DEBUG) +=3D kexec_handover_debug.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..ae8bdd87458a --- /dev/null +++ b/kernel/liveupdate/Kconfig @@ -0,0 +1,39 @@ +# 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_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. + +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..f52ce1ebcf86 --- /dev/null +++ b/kernel/liveupdate/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 + +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/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 6aa25d304bad..20c7a985828c 100644 --- a/kernel/kexec_handover.c +++ b/kernel/liveupdate/kexec_handover.c @@ -26,8 +26,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" diff --git a/kernel/kexec_handover_debug.c b/kernel/liveupdate/kexec_handov= er_debug.c similarity index 100% rename from kernel/kexec_handover_debug.c rename to kernel/liveupdate/kexec_handover_debug.c 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.1.821.gb6fe4d2222-goog From nobody Sun Feb 8 17:28:54 2026 Received: from mail-yw1-f171.google.com (mail-yw1-f171.google.com [209.85.128.171]) (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 F2D8A3385A3 for ; Fri, 24 Oct 2025 16:10:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761322215; cv=none; b=DNGtghR9krAz0kWkF6fkC8eNyAohrAKOdb8tmptboUinLoAo4G6zP3cESAqrEPYwIUTGP7HBaGmVPUH3C3/XmKflQ+wif1u3StnOhdtF2zg/GlJJ0bqqX2h14Ev+blP2WWUWSILf71QOVx5MYT+NZqNVgefr34gfnGD4ZE0tsgg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761322215; c=relaxed/simple; bh=47nCxyU4kXn+xfRtbLcXpCvIUy2KTrw5bnGeJZgJkWw=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=H3D6dkdTZesRfX42hDOa72c2bKNbjSeZwuIWCrAWdyXrzCacjOsiNVR5ECY+Ls+YqsnKg9fq71pVVy5PH4PE9uVa92tQ5MQOMl8Ieu9wV8113txL1IWvyppP7MpiHlrrPntHcvToftEfoXMs6PuXVfpcPqrwmRtUdn6qPlTLy6I= 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=VR+DuFIE; arc=none smtp.client-ip=209.85.128.171 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="VR+DuFIE" Received: by mail-yw1-f171.google.com with SMTP id 00721157ae682-783fa3af3bdso26857127b3.1 for ; Fri, 24 Oct 2025 09:10:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1761322212; x=1761927012; 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=J0Chij7I5YmPbNPLJtF290sPw75eaI56z9Bpyk1lLtA=; b=VR+DuFIE80cOY2YsniD2DX3xG0XoFuioW9AwWzsYivw9JAoDE4e3fVnhyoBIiUAMV7 kkX6qhuSX1cepInZRg4SbmWEc5605xT51vXKlfHIYygBreCXF8JwcjEyCuGYTeND7zy2 jBBzCulxBiZZ3q0mLTsk5lnlYQDORdKXG7pOBp+Ba9OmPwQwpvtwA2VPkjJPPHXZZz10 ARnAqSY67HL7/pDZhKLTKIY2AZm0pvYlYtEpruUQA7eTDeP7ngX5SzB5u/OgbpxyNRGP LVRpmGm/tFU3E/Q8HuflZYPTkhsZ3BIxGfT4I3zx9fylgLXKROBVe6b1a1HdwgXh6Jez wLtg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1761322212; x=1761927012; 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=J0Chij7I5YmPbNPLJtF290sPw75eaI56z9Bpyk1lLtA=; b=v78FPud0J90fMCMf7v4UFOc1eAuXC4bRiIlgsMDcj4/hQLbi/8b1QXIiGahzsvIhYs hU1i0hc2JnH/AkxMDtCgTjjxY/MgfstWlbqPS0SXjUN+Rqpy/0r7E2+c3/qn4oWT99rv JulPw+ZGHSsZX/6ueUN2T5CGNmsG4jmRmzu2oI/wR+47QkjxtcRcx9NNkxhtYmXlxM70 hnVR2t55PdGaiMXDrP6JweMAhM6pqOAWObheUsg0XmN3599yyIH2oMrZrsi9dxSrEfHH CtGgGZRAHT1JphskhVQj8NvlLIlSLE4Twx8stcdD7KEg7g4pPLEeYmXpleaTf666XYj2 Ttnw== X-Forwarded-Encrypted: i=1; AJvYcCXiuAG5AgGu+hfwLmQynYHlH03lYYT/b6dN1WlGmn8u6ZVuRoQElgniITP2rVlf+xgpYQ0dQfyt2Yhkz4g=@vger.kernel.org X-Gm-Message-State: AOJu0Yy/qU/6r4oU8AHy40uBP3eAIHIRzYcvBjdyyPYVRxQjHtM8AaST KiVHU98vvCnK5yhD5UY2uzpuAUQrkTiOPCrY/HnpSB0Ozt5Q2v9212nttzFSV7Eg5CU= X-Gm-Gg: ASbGncsYsTrtKPNX9TIA6/Tdg1wM2UTtBBkupsVGAPGDbl4UU8W5MdQC64B8W01gMFQ EGbAqjGvng8lqilCMo2I7XY5zEJex6AoGjSV3/ME8RcfWeVaT9Uu4EJXjDcJ3UytdWdt7FxtYr0 zHI/7cRziBrUsAMC3QZLYvC1fslOeqQN41w5ZISox4IsCXUoVjeBLe1Iyt9Y0RXVwkPPC5DaNYq 7qEJrU3VTKcSVVmKZtgUxJ044Tu/Lm16TfZzwo93bX5IcPiyPdMrOfAmHGSDZ+e8Iw5HC9Xkwfw 5EAONC2Q+hA9qx8PSMISdcT7dpBGUuTENepVAxGBTzVYpCHwRB3djYbJPqymNK4cJfb4UVHQbYN WjUvRlh/rcPGQgXW9FQrFObitoSkIQ4/SUL+uOy/dNwYKejPrVixiaR8Mjux4g5ojTlMvKreeHM cDNdICpnKEu/izlxD9yehZXiKrXfeXOC2XnmhM9CYeN2qCIbi4a/jw4kAovV+P6ZL0nxcbvXvJD RpKn2wNeVJ7RgXL2VUx4E0= X-Google-Smtp-Source: AGHT+IGrHktoB2+zSyNVNIoeQp5HcQOC7JtCZnm9h30tzfcmrjcwbTqgqHhgYQabiysiaKaamJl5yw== X-Received: by 2002:a05:690c:dd3:b0:780:fe72:934b with SMTP id 00721157ae682-785e0231474mr22622787b3.48.1761322211974; Fri, 24 Oct 2025 09:10:11 -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 00721157ae682-785cd6edd87sm14099197b3.51.2025.10.24.09.10.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Oct 2025 09:10:11 -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 Subject: [PATCH v8 7/8] liveupdate: kho: move kho debugfs directory to liveupdate Date: Fri, 24 Oct 2025 12:10:01 -0400 Message-ID: <20251024161002.747372-8-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.51.1.821.gb6fe4d2222-goog In-Reply-To: <20251024161002.747372-1-pasha.tatashin@soleen.com> References: <20251024161002.747372-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/ in order to keep current and upcoming LUO/KHO features organized. 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, kexec telemtry, and other users 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 46e9e6c0791f..454b7d34ddc3 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; @@ -118,7 +118,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; @@ -178,7 +178,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 @@ -212,8 +212,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 17ae101dc6ae..92798346fa5a 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.1.821.gb6fe4d2222-goog From nobody Sun Feb 8 17:28:54 2026 Received: from mail-yw1-f169.google.com (mail-yw1-f169.google.com [209.85.128.169]) (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 3FD8A338916 for ; Fri, 24 Oct 2025 16:10:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761322216; cv=none; b=ICU+khZ+tuO8tf4IIjUKNYYddquDue5dph7eitvtvBWTil+HGjVZ0CzE+pf50HLnf2Xf6pBglLYltOUjJGtUV/qwoPG3/LIlnAIqYSJL/JH89I4qpUNK2pSNAC/MUfZwFUavftptF5s8JR8IiR3gcyD7JnLbcEjwI+7vcz1z5MA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761322216; c=relaxed/simple; bh=LXACdztAUdRgfPn95Jp9ukzR3cpsHm6JsrVc+niAfW4=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ou9JcAUivu3VKkwes4tD8dg93BiK560kPGoJWk7J5iNBtUmVTWwVm1VLKQD6/RQ/NIvXoLBr3C4/73gNK6Uf9j4Nu6eSJM34kCH8wWqqYU8O/6OBLigbyzEoWQJaG8Y2XBiuxWTSLCeMkMGnHUhOiIuvNl1Px6VAyK7ycTnWZy0= 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=YgvlBGaa; arc=none smtp.client-ip=209.85.128.169 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="YgvlBGaa" Received: by mail-yw1-f169.google.com with SMTP id 00721157ae682-784a5f53e60so27118157b3.2 for ; Fri, 24 Oct 2025 09:10:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1761322213; x=1761927013; 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=kPI1gxitoc4b140sD8ZnWvGi4JoP4wU7snq/qHJbNDE=; b=YgvlBGaav8ky/8tj46mlpNM1ACIe1mAWkJSjMtNM6UP3fsMy1d5ptLjRtdgQ3dfjqd gH7b8bFzWr87JicBtJjvemkZ9BFg76p/uEBaE919cyaMK+QW7Eh5NbkH4rjZlfxHG/Wh MgPvm2xBI3+sKhj4XsDLa063NldWv/ThYsuQH+hdx3MhlJmHi1EC9uj0yTPxZtfMr9ty m3CKM8RDBYGIcNM+tZznrnwu5QQnBlQmN1khp5tgXhU2VE5gLKiYBXhvbeTHT/twQ/T5 2GO/08+HYokfYjqC+s/n5LMB24KK9/0yGvS4Go7a/tJSbTmQ4WWzuYACl5ud9kHlS2H+ PYlw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1761322213; x=1761927013; 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=kPI1gxitoc4b140sD8ZnWvGi4JoP4wU7snq/qHJbNDE=; b=aonE0RWu3/2M85hcLGqqB59oWdr4sZL98xGQkN7pPzWTjJtFvA14yKhXT7yvl9Osjn pOOhyK4A1nfDCotjW7prHE/W8n2cN9aPc3ru+F7sIR6RwP+tf0Ey7Fnwprd4DzHDY2nn qU/YBUpsL/u4cjY8k4x/SlnRny7Gje51y3BcQ4PQrpwb3c9aZ1gYr+3DEOkoKD0W2YtD xYit/XqW+oj60vVynVY98W1ZkR585oR9C1fs7Mdc6UX5d2sabMAd8fgsGyjEP03n3WY0 9dfzYhMR3V9KA/VA9QSNeWPsYoGeudCibmJDl66s1txVzEB7a1eIb9xwjnnPKNc/FYHF fmug== X-Forwarded-Encrypted: i=1; AJvYcCXiKaZFGOGm5cdOw1Tkh/2ArXpa5QPqT3zQ0b4qsVtqryemXpEOLgtvTCr6jl2yPoOCyQHN27CqvLfWHJY=@vger.kernel.org X-Gm-Message-State: AOJu0YysKq550PwqGodX8KwM051XUhj/KarFkTy6hYQZ5W5rJe6pc36k oE83foOOFp6BNfHJlgCR+kHgDXfFqP2zeJxxIMo+vHDLCOotYgG+0FoqgdPmylHF7eU= X-Gm-Gg: ASbGncuTdqQBi1cBjGLRYtc5i3i5A2WVRakpzWMasjOtcqD2BJ29MPMYYWJ/8HMlgOm NMSdvy/2eungV1Dn3OMiDLjI1p8mgek0Xzw8BvW3oJK6xoubeXP6qJi7sqWvWhUr3oL9Bv5XLdR SmtC/AnbknjJA3ZlbJk0axlrCP70qOKbNqgxDyNNrTzAIIbXFQcDUKkSKWhHf9r7RwTFTx246xT WtU1In1O3Nky+YpxwgZ5JWSrWSx3YJvFzZuGTiipmRBqgYlGumZWTc2QuahQrQLOUCyOG6rih30 P0L6lqSGlHxWBeoB+Dr5DixRvkRAsKg5nVRH8KGmcxa+Rl0wVmjhDMT+BGJZU3Gvm1Obr2bPVeX AvbOd37j2LQz+GDDqG7CArrrp2WosqFAIFqqQKtv8nKSjvzML3KUsEYocABSUK7JSpJpYJK5YdE xacICgmxV2BSeg6oGEWbCO/bRxXwQA8BCJzfUrXbsfD83twMIMPS1uORHdSqTbNf9P3gsxCeAt1 cCO9TV14LfDdWbZ/5Ah++yj/0Lu1EJs4A== X-Google-Smtp-Source: AGHT+IHNLH1g3W3lGanu9RY51vSAbD6c3rZHsTMEnjrgcijU+Yq4oR9AGojuFoR3I5TlxNSrGCNhOw== X-Received: by 2002:a05:690c:253:b0:781:64f:312c with SMTP id 00721157ae682-7836dd58f3emr189766937b3.58.1761322213053; Fri, 24 Oct 2025 09:10:13 -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 00721157ae682-785cd6edd87sm14099197b3.51.2025.10.24.09.10.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Oct 2025 09:10:12 -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 Subject: [PATCH v8 8/8] memblock: Unpreserve memory in case of error Date: Fri, 24 Oct 2025 12:10:02 -0400 Message-ID: <20251024161002.747372-9-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.51.1.821.gb6fe4d2222-goog In-Reply-To: <20251024161002.747372-1-pasha.tatashin@soleen.com> References: <20251024161002.747372-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" If there is an error half way through KHO memory preservation, we should rollback and unpreserve everything that is partially preserved. Signed-off-by: Pasha Tatashin Suggested-by: Pratyush Yadav Reviewed-by: Pratyush Yadav --- mm/memblock.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/mm/memblock.c b/mm/memblock.c index e3bef9b35d63..5ceaa02af7d6 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -2447,6 +2447,7 @@ int reserve_mem_release_by_name(const char *name) =20 static int __init prepare_kho_fdt(void) { + bool fdt_folio_preserved =3D false; int err =3D 0, i; struct page *fdt_page; void *fdt; @@ -2462,12 +2463,14 @@ static int __init prepare_kho_fdt(void) =20 err |=3D fdt_begin_node(fdt, ""); err |=3D fdt_property_string(fdt, "compatible", MEMBLOCK_KHO_NODE_COMPATI= BLE); - for (i =3D 0; i < reserved_mem_count; i++) { + for (i =3D 0; !err && 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 kho_preserve_pages(page, nr_pages); + if (err) + break; 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)); @@ -2477,12 +2480,27 @@ static int __init prepare_kho_fdt(void) 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_preserve_folio(page_folio(fdt_page)); + + if (!err) { + fdt_folio_preserved =3D true; err =3D kho_add_subtree(MEMBLOCK_KHO_FDT, fdt); + } =20 if (err) { + int nr_reserve_map_preserved =3D i; + + for (i =3D 0; i < nr_reserve_map_preserved; 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; + + kho_unpreserve_pages(page, nr_pages); + } + if (fdt_folio_preserved) + kho_unpreserve_folio(page_folio(fdt_page)); + pr_err("failed to prepare memblock FDT for KHO: %d\n", err); put_page(fdt_page); } --=20 2.51.1.821.gb6fe4d2222-goog