From nobody Mon Oct 6 08:26:54 2025 Received: from mail-yw1-f176.google.com (mail-yw1-f176.google.com [209.85.128.176]) (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 B7CE42FBFEE for ; Wed, 23 Jul 2025 14:47:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753282051; cv=none; b=nKHh2L2QPQVEwzSM/c8o74RkJmtmGsPNu5gMcCqps044SbL+gVnHhg813ktfjXByR9l150SmPmk+zfw6aYhmcUe47CtV4y2FcPGj6u6ckj8SzRXszegUJj/S7Rh+n7N26UlEuYsILtg53W+obVMRYRSHLrkfg0f5R2vEjPLdibY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1753282051; c=relaxed/simple; bh=68fuMsTaKD3Wnucw9AAh9zoVaQeYptH5ixtgvH+HmAU=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PM+qvn/2JKFe5sSBB7IWXHQuu1rseHud/e8XVbxvdeIlRB0C1pWPLr5rJBIOp6UHogXdv9yEF7+iDfsGa8RhJjnTt1AB5qaOm3cie3tlxfqCCazBYhpCoKTLn5MfhqXQL98BKp2/K6Zyx0y0IpQBkc1v2S4xjgzavpfcAANWvog= 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.20230601.gappssmtp.com header.i=@soleen-com.20230601.gappssmtp.com header.b=R44ljpeW; arc=none smtp.client-ip=209.85.128.176 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.20230601.gappssmtp.com header.i=@soleen-com.20230601.gappssmtp.com header.b="R44ljpeW" Received: by mail-yw1-f176.google.com with SMTP id 00721157ae682-70e3e0415a7so260047b3.0 for ; Wed, 23 Jul 2025 07:47:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen-com.20230601.gappssmtp.com; s=20230601; t=1753282037; x=1753886837; 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=4F1QX9qtkry2jc2ztpFtzfSo3tcuBncamP+UfSK+M08=; b=R44ljpeW2aiUQPfSpcsXyKfWL0rEO+j985Kvz9qQhp6c9j3CJpFHLVIQXjxjFKQwK7 0WmqXf0Jmoikod9rFQgELrjEGYP2GhaOXbZYlwPTRLbXcEi1kn54GLEevMlmoo7BgmXi ATqVRpOE+dUiVkXhAE7MWaGtcpw4E108QvVjQxqfKhUb5COaIdtWBp0QdIA4xBUQD9bU 6QkBptdXncY+2Q/lCzhQztkdndKNGkXXJptXGHKIoyicZfMIB3+/+39kf4+gyi+eOpOM 1ZJpOdK50YuYw999wktw5RKsIHdsBGbzkmi8mwACPXzNlYs69FGg5Utndu7GQLbosymO NU4Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1753282037; x=1753886837; 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=4F1QX9qtkry2jc2ztpFtzfSo3tcuBncamP+UfSK+M08=; b=VqBFsm4UKpvagaQmqfLkrAeVB80R6kJ5GWe1RdPAvSKoH3yr5V9znvQTU8QHCITOH/ 96AWZHAk75xq7WOC643PLgW0uIJb/UlTzV2kWJK2IEMauafSO/fA98azPiU6167e2cUt jeIJGZ3osj65FYGf6lHMTo/i2gyyRCq4CKZLk10D5YtPZaAnSYro9dzC92BHRhiMNBXu 46BeqChYGlN5ehVYBPhWR9ELDZRuDAaYY0JzhsHD3Yb+XlmYQTMGQWfIVf7NKDAoBuqz aKjkDFvYoYUrUSD6kw3xP8o4wGW5jms6J81ygjOwt6TntZu3NbXfhfnTUJ7pbu/DfQGm tBkw== X-Forwarded-Encrypted: i=1; AJvYcCWacXBb4EWk9kP/NZlINb6RykwaRxkoe7KOTy53y7uNq1hailHx3WALIsGQbLUAyOYqXBlEJY3uQAtkbaA=@vger.kernel.org X-Gm-Message-State: AOJu0Yz/57C6KW17ZtRwCPoqEXSGwMAWD8XX71HN7GHytxwR+0gSGd/6 baBzzvtHsJAx8O80H2tNssQVmFPexBufbObJuxhuJ+JP6yaDvblvZELq2v38TaTq8YQ= X-Gm-Gg: ASbGncvJS7JiC01hTEox59xu4GAXn9Y8ERpfH/mG1lxSjfmRCD9N9wx9Id2TrVCKV1d cjnTB45b2aEIEYiRa48IOUS+k9OftD4eumfT2jtckV3ktdPXKcM9nUucUcrf84kqDsg3jugKMW7 AIjRHleCCdiLocm+rusmx5cLNBHXnEo+AwGeBAouSH5ioZ4wRzagL4hLuk7vQTBo1YFRUP5hH9K VUVZMStPPVbVnuavYTFETeVCuffj1stUXKzqfVLHUosv+yG7lFC/ztIw68TRg0GgJAqrxKb0vwV O1REFA6R3f6SMvX6l9/9PZBGIeXLHD+mBeY2ifJ+QwKlhjDs2B0oOBfMU7zPqmSusBMQJ8SqNeA UkchKcM5TvWPoJMndTG7zVfqgWMR4I19TdstDE60YmMjAW9ZzhidmPL0wNgi6r68nC7NCDHXj56 uJ0nuTPbNftR8OMA== X-Google-Smtp-Source: AGHT+IGIKplQvsQ6oyU5xYVnnj9HKRC7xjC99zYFucpfaGhtR6VBuuTxNds+2TPsqRP8M9w0Avf/qg== X-Received: by 2002:a05:690c:60c7:b0:712:cc11:b02 with SMTP id 00721157ae682-719a0a12ea1mr108397577b3.4.1753282036550; Wed, 23 Jul 2025 07:47:16 -0700 (PDT) Received: from soleen.c.googlers.com.com (235.247.85.34.bc.googleusercontent.com. [34.85.247.235]) by smtp.gmail.com with ESMTPSA id 00721157ae682-719532c7e4fsm30482117b3.72.2025.07.23.07.47.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 23 Jul 2025 07:47:16 -0700 (PDT) From: Pasha Tatashin To: pratyush@kernel.org, jasonmiu@google.com, graf@amazon.com, changyuanl@google.com, pasha.tatashin@soleen.com, rppt@kernel.org, dmatlack@google.com, rientjes@google.com, corbet@lwn.net, rdunlap@infradead.org, ilpo.jarvinen@linux.intel.com, kanie@linux.alibaba.com, ojeda@kernel.org, aliceryhl@google.com, masahiroy@kernel.org, akpm@linux-foundation.org, tj@kernel.org, yoann.congal@smile.fr, mmaurer@google.com, roman.gushchin@linux.dev, chenridong@huawei.com, axboe@kernel.dk, mark.rutland@arm.com, jannh@google.com, vincent.guittot@linaro.org, hannes@cmpxchg.org, dan.j.williams@intel.com, david@redhat.com, joel.granados@kernel.org, rostedt@goodmis.org, anna.schumaker@oracle.com, song@kernel.org, zhangguopeng@kylinos.cn, linux@weissschuh.net, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-mm@kvack.org, gregkh@linuxfoundation.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, rafael@kernel.org, dakr@kernel.org, bartosz.golaszewski@linaro.org, cw00.choi@samsung.com, myungjoo.ham@samsung.com, yesanishhere@gmail.com, Jonathan.Cameron@huawei.com, quic_zijuhu@quicinc.com, aleksander.lobakin@intel.com, ira.weiny@intel.com, andriy.shevchenko@linux.intel.com, leon@kernel.org, lukas@wunner.de, bhelgaas@google.com, wagi@kernel.org, djeffery@redhat.com, stuart.w.hayes@gmail.com, ptyadav@amazon.de, lennart@poettering.net, brauner@kernel.org, linux-api@vger.kernel.org, linux-fsdevel@vger.kernel.org, saeedm@nvidia.com, ajayachandra@nvidia.com, jgg@nvidia.com, parav@nvidia.com, leonro@nvidia.com, witu@nvidia.com Subject: [PATCH v2 11/32] liveupdate: luo_core: integrate with KHO Date: Wed, 23 Jul 2025 14:46:24 +0000 Message-ID: <20250723144649.1696299-12-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.50.0.727.gbf7dc18ff4-goog In-Reply-To: <20250723144649.1696299-1-pasha.tatashin@soleen.com> References: <20250723144649.1696299-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" Integrate the LUO with the KHO framework to enable passing LUO state across a kexec reboot. When LUO is transitioned to a "prepared" state, it tells KHO to finalize, so all memory segments that were added to KHO preservation list are getting preserved. After "Prepared" state no new segments can be preserved. If LUO is canceled, it also tells KHO to cancel the serialization, and therefore, later LUO can go back into the prepared state. This patch introduces the following changes: - During the KHO finalization phase allocate FDT blob. - Populate this FDT with a LUO compatibility string ("luo-v1"). - Implement a KHO notifier LUO now depends on `CONFIG_KEXEC_HANDOVER`. The core state transition logic (`luo_do_*_calls`) remains unimplemented in this patch. Signed-off-by: Pasha Tatashin --- kernel/liveupdate/luo_core.c | 214 ++++++++++++++++++++++++++++++++++- 1 file changed, 211 insertions(+), 3 deletions(-) diff --git a/kernel/liveupdate/luo_core.c b/kernel/liveupdate/luo_core.c index 8cee093807ff..c80a1f188359 100644 --- a/kernel/liveupdate/luo_core.c +++ b/kernel/liveupdate/luo_core.c @@ -47,9 +47,12 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt =20 #include +#include #include +#include #include #include +#include #include #include "luo_internal.h" =20 @@ -67,6 +70,21 @@ static const char *const luo_state_str[] =3D { =20 static bool luo_enabled; =20 +static void *luo_fdt_out; +static void *luo_fdt_in; + +/* + * The LUO FDT size depends on the number of participating subsystems, + * + * The current fixed size (4K) is large enough to handle reasonable number= of + * preserved entities. If this size ever becomes insufficient, it can eith= er be + * increased, or a dynamic size calculation mechanism could be implemented= in + * the future. + */ +#define LUO_FDT_SIZE PAGE_SIZE +#define LUO_KHO_ENTRY_NAME "LUO" +#define LUO_COMPATIBLE "luo-v1" + static int __init early_liveupdate_param(char *buf) { return kstrtobool(buf, &luo_enabled); @@ -91,6 +109,60 @@ static inline void luo_set_state(enum liveupdate_state = state) __luo_set_state(state); } =20 +/* Called during the prepare phase, to create LUO fdt tree */ +static int luo_fdt_setup(void) +{ + void *fdt_out; + int ret; + + fdt_out =3D (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, + get_order(LUO_FDT_SIZE)); + if (!fdt_out) { + pr_err("failed to allocate FDT memory\n"); + return -ENOMEM; + } + + ret =3D fdt_create_empty_tree(fdt_out, LUO_FDT_SIZE); + if (ret) + goto exit_free; + + ret =3D fdt_setprop_string(fdt_out, 0, "compatible", LUO_COMPATIBLE); + if (ret) + goto exit_free; + + ret =3D kho_preserve_phys(__pa(fdt_out), LUO_FDT_SIZE); + if (ret) + goto exit_free; + + ret =3D kho_add_subtree(LUO_KHO_ENTRY_NAME, fdt_out); + if (ret) + goto exit_unpreserve; + luo_fdt_out =3D fdt_out; + + return 0; + +exit_unpreserve: + WARN_ON_ONCE(kho_unpreserve_phys(__pa(fdt_out), LUO_FDT_SIZE)); +exit_free: + free_pages((unsigned long)fdt_out, get_order(LUO_FDT_SIZE)); + pr_err("failed to prepare LUO FDT: %d\n", ret); + + return ret; +} + +static void luo_fdt_destroy(void) +{ + WARN_ON_ONCE(kho_unpreserve_phys(__pa(luo_fdt_out), LUO_FDT_SIZE)); + kho_remove_subtree(luo_fdt_out); + free_pages((unsigned long)luo_fdt_out, get_order(LUO_FDT_SIZE)); + luo_fdt_out =3D NULL; +} + +static int luo_do_prepare_calls(void) +{ + return 0; +} + static int luo_do_freeze_calls(void) { return 0; @@ -100,6 +172,71 @@ static void luo_do_finish_calls(void) { } =20 +static void luo_do_cancel_calls(void) +{ +} + +static int __luo_prepare(void) +{ + int ret; + + if (down_write_killable(&luo_state_rwsem)) { + pr_warn("[prepare] event canceled by user\n"); + return -EAGAIN; + } + + if (!is_current_luo_state(LIVEUPDATE_STATE_NORMAL)) { + pr_warn("Can't switch to [%s] from [%s] state\n", + luo_state_str[LIVEUPDATE_STATE_PREPARED], + luo_current_state_str()); + ret =3D -EINVAL; + goto exit_unlock; + } + + ret =3D luo_fdt_setup(); + if (ret) + goto exit_unlock; + + ret =3D luo_do_prepare_calls(); + if (ret) { + luo_fdt_destroy(); + goto exit_unlock; + } + + luo_set_state(LIVEUPDATE_STATE_PREPARED); + +exit_unlock: + up_write(&luo_state_rwsem); + + return ret; +} + +static int __luo_cancel(void) +{ + if (down_write_killable(&luo_state_rwsem)) { + pr_warn("[cancel] event canceled by user\n"); + return -EAGAIN; + } + + if (!is_current_luo_state(LIVEUPDATE_STATE_PREPARED) && + !is_current_luo_state(LIVEUPDATE_STATE_FROZEN)) { + pr_warn("Can't switch to [%s] from [%s] state\n", + luo_state_str[LIVEUPDATE_STATE_NORMAL], + luo_current_state_str()); + up_write(&luo_state_rwsem); + + return -EINVAL; + } + + luo_do_cancel_calls(); + luo_fdt_destroy(); + luo_set_state(LIVEUPDATE_STATE_NORMAL); + + up_write(&luo_state_rwsem); + + return 0; +} + /* Get the current state as a string */ const char *luo_current_state_str(void) { @@ -111,9 +248,28 @@ enum liveupdate_state liveupdate_get_state(void) return READ_ONCE(luo_state); } =20 +/** + * luo_prepare - Initiate the live update preparation phase. + * + * This function is called to begin the live update process. It attempts to + * transition the luo to the ``LIVEUPDATE_STATE_PREPARED`` state. + * + * If the calls complete successfully, the orchestrator state is set + * to ``LIVEUPDATE_STATE_PREPARED``. If any call fails a + * ``LIVEUPDATE_CANCEL`` is sent to roll back any actions. + * + * @return 0 on success, ``-EAGAIN`` if the state change was cancelled by = the + * user while waiting for the lock, ``-EINVAL`` if the orchestrator is not= in + * the normal state, or a negative error code returned by the calls. + */ int luo_prepare(void) { - return 0; + int err =3D __luo_prepare(); + + if (err) + return err; + + return kho_finalize(); } =20 /** @@ -193,9 +349,28 @@ int luo_finish(void) return 0; } =20 +/** + * luo_cancel - Cancel the ongoing live update from prepared or frozen sta= tes. + * + * This function is called to abort a live update that is currently in the + * ``LIVEUPDATE_STATE_PREPARED`` state. + * + * If the state is correct, it triggers the ``LIVEUPDATE_CANCEL`` notifier= chain + * to allow subsystems to undo any actions performed during the prepare or + * freeze events. Finally, the orchestrator state is transitioned back to + * ``LIVEUPDATE_STATE_NORMAL``. + * + * @return 0 on success, or ``-EAGAIN`` if the state change was cancelled = by the + * user while waiting for the lock. + */ int luo_cancel(void) { - return 0; + int err =3D kho_abort(); + + if (err) + return err; + + return __luo_cancel(); } =20 void luo_state_read_enter(void) @@ -210,7 +385,40 @@ void luo_state_read_exit(void) =20 static int __init luo_startup(void) { - __luo_set_state(LIVEUPDATE_STATE_NORMAL); + phys_addr_t fdt_phys; + int ret; + + if (!kho_is_enabled()) { + if (luo_enabled) + pr_warn("Disabling liveupdate because KHO is disabled\n"); + luo_enabled =3D false; + return 0; + } + + /* + * Retrieve LUO subtree, and verify its format. Panic in case of + * exceptions, since machine devices and memory is in unpredictable + * state. + */ + ret =3D kho_retrieve_subtree(LUO_KHO_ENTRY_NAME, &fdt_phys); + if (ret) { + if (ret !=3D -ENOENT) { + panic("failed to retrieve FDT '%s' from KHO: %d\n", + LUO_KHO_ENTRY_NAME, ret); + } + __luo_set_state(LIVEUPDATE_STATE_NORMAL); + + return 0; + } + + luo_fdt_in =3D __va(fdt_phys); + ret =3D fdt_node_check_compatible(luo_fdt_in, 0, LUO_COMPATIBLE); + if (ret) { + panic("FDT '%s' is incompatible with '%s' [%d]\n", + LUO_KHO_ENTRY_NAME, LUO_COMPATIBLE, ret); + } + + __luo_set_state(LIVEUPDATE_STATE_UPDATED); =20 return 0; } --=20 2.50.0.727.gbf7dc18ff4-goog