xref: /linux/kernel/liveupdate/luo_flb.c (revision 6b2b22f7c8cf1596490beaac96a989cbafdfea57)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 /*
4  * Copyright (c) 2025, Google LLC.
5  * Pasha Tatashin <pasha.tatashin@soleen.com>
6  */
7 
8 /**
9  * DOC: LUO File Lifecycle Bound Global Data
10  *
11  * File-Lifecycle-Bound (FLB) objects provide a mechanism for managing global
12  * state that is shared across multiple live-updatable files. The lifecycle of
13  * this shared state is tied to the preservation of the files that depend on it.
14  *
15  * An FLB represents a global resource, such as the IOMMU core state, that is
16  * required by multiple file descriptors (e.g., all VFIO fds).
17  *
18  * The preservation of the FLB's state is triggered when the *first* file
19  * depending on it is preserved. The cleanup of this state (unpreserve or
20  * finish) is triggered when the *last* file depending on it is unpreserved or
21  * finished.
22  *
23  * Handler Dependency: A file handler declares its dependency on one or more
24  * FLBs by registering them via liveupdate_register_flb().
25  *
26  * Callback Model: Each FLB is defined by a set of operations
27  * (&struct liveupdate_flb_ops) that LUO invokes at key points:
28  *
29  *     - .preserve(): Called for the first file. Saves global state.
30  *     - .unpreserve(): Called for the last file (if aborted pre-reboot).
31  *     - .retrieve(): Called on-demand in the new kernel to restore the state.
32  *     - .finish(): Called for the last file in the new kernel for cleanup.
33  *
34  * This reference-counted approach ensures that shared state is saved exactly
35  * once and restored exactly once, regardless of how many files depend on it,
36  * and that its lifecycle is correctly managed across the kexec transition.
37  */
38 
39 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
40 
41 #include <linux/cleanup.h>
42 #include <linux/err.h>
43 #include <linux/errno.h>
44 #include <linux/io.h>
45 #include <linux/kexec_handover.h>
46 #include <linux/kho/abi/luo.h>
47 #include <linux/libfdt.h>
48 #include <linux/list_private.h>
49 #include <linux/liveupdate.h>
50 #include <linux/module.h>
51 #include <linux/mutex.h>
52 #include <linux/slab.h>
53 #include <linux/unaligned.h>
54 #include "luo_internal.h"
55 
56 #define LUO_FLB_PGCNT		1ul
57 #define LUO_FLB_MAX		(((LUO_FLB_PGCNT << PAGE_SHIFT) -	\
58 		sizeof(struct luo_flb_header_ser)) / sizeof(struct luo_flb_ser))
59 
60 struct luo_flb_header {
61 	struct luo_flb_header_ser *header_ser;
62 	struct luo_flb_ser *ser;
63 	bool active;
64 };
65 
66 struct luo_flb_global {
67 	struct luo_flb_header incoming;
68 	struct luo_flb_header outgoing;
69 	struct list_head list;
70 	long count;
71 };
72 
73 static struct luo_flb_global luo_flb_global = {
74 	.list = LIST_HEAD_INIT(luo_flb_global.list),
75 };
76 
77 /*
78  * struct luo_flb_link - Links an FLB definition to a file handler's internal
79  * list of dependencies.
80  * @flb:  A pointer to the registered &struct liveupdate_flb definition.
81  * @list: The list_head for linking.
82  */
83 struct luo_flb_link {
84 	struct liveupdate_flb *flb;
85 	struct list_head list;
86 };
87 
88 /* luo_flb_get_private - Access private field, and if needed initialize it. */
89 static struct luo_flb_private *luo_flb_get_private(struct liveupdate_flb *flb)
90 {
91 	struct luo_flb_private *private = &ACCESS_PRIVATE(flb, private);
92 	static DEFINE_SPINLOCK(luo_flb_init_lock);
93 
94 	if (smp_load_acquire(&private->initialized))
95 		return private;
96 
97 	guard(spinlock)(&luo_flb_init_lock);
98 	if (!private->initialized) {
99 		mutex_init(&private->incoming.lock);
100 		mutex_init(&private->outgoing.lock);
101 		INIT_LIST_HEAD(&private->list);
102 		private->users = 0;
103 		smp_store_release(&private->initialized, true);
104 	}
105 
106 	return private;
107 }
108 
109 static int luo_flb_file_preserve_one(struct liveupdate_flb *flb)
110 {
111 	struct luo_flb_private *private = luo_flb_get_private(flb);
112 
113 	scoped_guard(mutex, &private->outgoing.lock) {
114 		if (!private->outgoing.count) {
115 			struct liveupdate_flb_op_args args = {0};
116 			int err;
117 
118 			args.flb = flb;
119 			err = flb->ops->preserve(&args);
120 			if (err)
121 				return err;
122 			private->outgoing.data = args.data;
123 			private->outgoing.obj = args.obj;
124 		}
125 		private->outgoing.count++;
126 	}
127 
128 	return 0;
129 }
130 
131 static void luo_flb_file_unpreserve_one(struct liveupdate_flb *flb)
132 {
133 	struct luo_flb_private *private = luo_flb_get_private(flb);
134 
135 	scoped_guard(mutex, &private->outgoing.lock) {
136 		private->outgoing.count--;
137 		if (!private->outgoing.count) {
138 			struct liveupdate_flb_op_args args = {0};
139 
140 			args.flb = flb;
141 			args.data = private->outgoing.data;
142 			args.obj = private->outgoing.obj;
143 
144 			if (flb->ops->unpreserve)
145 				flb->ops->unpreserve(&args);
146 
147 			private->outgoing.data = 0;
148 			private->outgoing.obj = NULL;
149 		}
150 	}
151 }
152 
153 static int luo_flb_retrieve_one(struct liveupdate_flb *flb)
154 {
155 	struct luo_flb_private *private = luo_flb_get_private(flb);
156 	struct luo_flb_header *fh = &luo_flb_global.incoming;
157 	struct liveupdate_flb_op_args args = {0};
158 	bool found = false;
159 	int err;
160 
161 	guard(mutex)(&private->incoming.lock);
162 
163 	if (private->incoming.finished)
164 		return -ENODATA;
165 
166 	if (private->incoming.retrieved)
167 		return 0;
168 
169 	if (!fh->active)
170 		return -ENODATA;
171 
172 	for (int i = 0; i < fh->header_ser->count; i++) {
173 		if (!strcmp(fh->ser[i].name, flb->compatible)) {
174 			private->incoming.data = fh->ser[i].data;
175 			private->incoming.count = fh->ser[i].count;
176 			found = true;
177 			break;
178 		}
179 	}
180 
181 	if (!found)
182 		return -ENOENT;
183 
184 	args.flb = flb;
185 	args.data = private->incoming.data;
186 
187 	err = flb->ops->retrieve(&args);
188 	if (err)
189 		return err;
190 
191 	private->incoming.obj = args.obj;
192 	private->incoming.retrieved = true;
193 
194 	return 0;
195 }
196 
197 static void luo_flb_file_finish_one(struct liveupdate_flb *flb)
198 {
199 	struct luo_flb_private *private = luo_flb_get_private(flb);
200 	u64 count;
201 
202 	scoped_guard(mutex, &private->incoming.lock)
203 		count = --private->incoming.count;
204 
205 	if (!count) {
206 		struct liveupdate_flb_op_args args = {0};
207 
208 		if (!private->incoming.retrieved) {
209 			int err = luo_flb_retrieve_one(flb);
210 
211 			if (WARN_ON(err))
212 				return;
213 		}
214 
215 		scoped_guard(mutex, &private->incoming.lock) {
216 			args.flb = flb;
217 			args.obj = private->incoming.obj;
218 			flb->ops->finish(&args);
219 
220 			private->incoming.data = 0;
221 			private->incoming.obj = NULL;
222 			private->incoming.finished = true;
223 		}
224 	}
225 }
226 
227 /**
228  * luo_flb_file_preserve - Notifies FLBs that a file is about to be preserved.
229  * @fh: The file handler for the preserved file.
230  *
231  * This function iterates through all FLBs associated with the given file
232  * handler. It increments the reference count for each FLB. If the count becomes
233  * 1, it triggers the FLB's .preserve() callback to save the global state.
234  *
235  * This operation is atomic. If any FLB's .preserve() op fails, it will roll
236  * back by calling .unpreserve() on any FLBs that were successfully preserved
237  * during this call.
238  *
239  * Context: Called from luo_preserve_file()
240  * Return: 0 on success, or a negative errno on failure.
241  */
242 int luo_flb_file_preserve(struct liveupdate_file_handler *fh)
243 {
244 	struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list);
245 	struct luo_flb_link *iter;
246 	int err = 0;
247 
248 	down_read(&luo_register_rwlock);
249 	list_for_each_entry(iter, flb_list, list) {
250 		err = luo_flb_file_preserve_one(iter->flb);
251 		if (err)
252 			goto exit_err;
253 	}
254 	up_read(&luo_register_rwlock);
255 
256 	return 0;
257 
258 exit_err:
259 	list_for_each_entry_continue_reverse(iter, flb_list, list)
260 		luo_flb_file_unpreserve_one(iter->flb);
261 	up_read(&luo_register_rwlock);
262 
263 	return err;
264 }
265 
266 /**
267  * luo_flb_file_unpreserve - Notifies FLBs that a dependent file was unpreserved.
268  * @fh: The file handler for the unpreserved file.
269  *
270  * This function iterates through all FLBs associated with the given file
271  * handler, in reverse order of registration. It decrements the reference count
272  * for each FLB. If the count becomes 0, it triggers the FLB's .unpreserve()
273  * callback to clean up the global state.
274  *
275  * Context: Called when a preserved file is being cleaned up before reboot
276  *          (e.g., from luo_file_unpreserve_files()).
277  */
278 void luo_flb_file_unpreserve(struct liveupdate_file_handler *fh)
279 {
280 	struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list);
281 	struct luo_flb_link *iter;
282 
283 	guard(rwsem_read)(&luo_register_rwlock);
284 	list_for_each_entry_reverse(iter, flb_list, list)
285 		luo_flb_file_unpreserve_one(iter->flb);
286 }
287 
288 /**
289  * luo_flb_file_finish - Notifies FLBs that a dependent file has been finished.
290  * @fh: The file handler for the finished file.
291  *
292  * This function iterates through all FLBs associated with the given file
293  * handler, in reverse order of registration. It decrements the incoming
294  * reference count for each FLB. If the count becomes 0, it triggers the FLB's
295  * .finish() callback for final cleanup in the new kernel.
296  *
297  * Context: Called from luo_file_finish() for each file being finished.
298  */
299 void luo_flb_file_finish(struct liveupdate_file_handler *fh)
300 {
301 	struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list);
302 	struct luo_flb_link *iter;
303 
304 	guard(rwsem_read)(&luo_register_rwlock);
305 	list_for_each_entry_reverse(iter, flb_list, list)
306 		luo_flb_file_finish_one(iter->flb);
307 }
308 
309 /**
310  * liveupdate_register_flb - Associate an FLB with a file handler and register it globally.
311  * @fh:   The file handler that will now depend on the FLB.
312  * @flb:  The File-Lifecycle-Bound object to associate.
313  *
314  * Establishes a dependency, informing the LUO core that whenever a file of
315  * type @fh is preserved, the state of @flb must also be managed.
316  *
317  * On the first registration of a given @flb object, it is added to a global
318  * registry. This function checks for duplicate registrations, both for a
319  * specific handler and globally, and ensures the total number of unique
320  * FLBs does not exceed the system limit.
321  *
322  * Context: Typically called from a subsystem's module init function after
323  *          both the handler and the FLB have been defined and initialized.
324  * Return: 0 on success. Returns a negative errno on failure:
325  *         -EINVAL if arguments are NULL or not initialized.
326  *         -ENOMEM on memory allocation failure.
327  *         -EEXIST if this FLB is already registered with this handler.
328  *         -ENOSPC if the maximum number of global FLBs has been reached.
329  *         -EOPNOTSUPP if live update is disabled or not configured.
330  */
331 int liveupdate_register_flb(struct liveupdate_file_handler *fh,
332 			    struct liveupdate_flb *flb)
333 {
334 	struct luo_flb_private *private = luo_flb_get_private(flb);
335 	struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list);
336 	struct luo_flb_link *link __free(kfree) = NULL;
337 	struct liveupdate_flb *gflb;
338 	struct luo_flb_link *iter;
339 	int err;
340 
341 	if (!liveupdate_enabled())
342 		return -EOPNOTSUPP;
343 
344 	if (WARN_ON(!flb->ops->preserve || !flb->ops->unpreserve ||
345 		    !flb->ops->retrieve || !flb->ops->finish)) {
346 		return -EINVAL;
347 	}
348 
349 	/*
350 	 * File handler must already be registered, as it initializes the
351 	 * flb_list
352 	 */
353 	if (WARN_ON(list_empty(&ACCESS_PRIVATE(fh, list))))
354 		return -EINVAL;
355 
356 	link = kzalloc_obj(*link);
357 	if (!link)
358 		return -ENOMEM;
359 
360 	/*
361 	 * Ensure the system is quiescent (no active sessions).
362 	 * This acts as a global lock for registration: no other thread can
363 	 * be in this section, and no sessions can be creating/using FDs.
364 	 */
365 	if (!luo_session_quiesce())
366 		return -EBUSY;
367 
368 	down_write(&luo_register_rwlock);
369 
370 	/* Check that this FLB is not already linked to this file handler */
371 	err = -EEXIST;
372 	list_for_each_entry(iter, flb_list, list) {
373 		if (iter->flb == flb)
374 			goto err_resume;
375 	}
376 
377 	/*
378 	 * If this FLB is not linked to global list it's the first time the FLB
379 	 * is registered
380 	 */
381 	if (!private->users) {
382 		if (WARN_ON(!list_empty(&private->list))) {
383 			err = -EINVAL;
384 			goto err_resume;
385 		}
386 
387 		if (luo_flb_global.count == LUO_FLB_MAX) {
388 			err = -ENOSPC;
389 			goto err_resume;
390 		}
391 
392 		/* Check that compatible string is unique in global list */
393 		list_private_for_each_entry(gflb, &luo_flb_global.list, private.list) {
394 			if (!strcmp(gflb->compatible, flb->compatible))
395 				goto err_resume;
396 		}
397 
398 		if (!try_module_get(flb->ops->owner)) {
399 			err = -EAGAIN;
400 			goto err_resume;
401 		}
402 
403 		list_add_tail(&private->list, &luo_flb_global.list);
404 		luo_flb_global.count++;
405 	}
406 
407 	/* Finally, link the FLB to the file handler */
408 	private->users++;
409 	link->flb = flb;
410 	list_add_tail(&no_free_ptr(link)->list, flb_list);
411 	up_write(&luo_register_rwlock);
412 	luo_session_resume();
413 
414 	return 0;
415 
416 err_resume:
417 	up_write(&luo_register_rwlock);
418 	luo_session_resume();
419 	return err;
420 }
421 
422 /**
423  * liveupdate_unregister_flb - Remove an FLB dependency from a file handler.
424  * @fh:   The file handler that is currently depending on the FLB.
425  * @flb:  The File-Lifecycle-Bound object to remove.
426  *
427  * Removes the association between the specified file handler and the FLB
428  * previously established by liveupdate_register_flb().
429  *
430  * This function manages the global lifecycle of the FLB. It decrements the
431  * FLB's usage count. If this was the last file handler referencing this FLB,
432  * the FLB is removed from the global registry and the reference to its
433  * owner module (acquired during registration) is released.
434  *
435  * Context: This function ensures the session is quiesced (no active FDs
436  *          being created) during the update. It is typically called from a
437  *          subsystem's module exit function.
438  * Return: 0 on success.
439  *         -EOPNOTSUPP if live update is disabled.
440  *         -EBUSY if the live update session is active and cannot be quiesced.
441  *         -ENOENT if the FLB was not found in the file handler's list.
442  */
443 int liveupdate_unregister_flb(struct liveupdate_file_handler *fh,
444 			      struct liveupdate_flb *flb)
445 {
446 	struct luo_flb_private *private = luo_flb_get_private(flb);
447 	struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list);
448 	struct luo_flb_link *iter;
449 	int err = -ENOENT;
450 
451 	if (!liveupdate_enabled())
452 		return -EOPNOTSUPP;
453 
454 	/*
455 	 * Ensure the system is quiescent (no active sessions).
456 	 * This acts as a global lock for unregistration.
457 	 */
458 	if (!luo_session_quiesce())
459 		return -EBUSY;
460 
461 	down_write(&luo_register_rwlock);
462 
463 	/* Find and remove the link from the file handler's list */
464 	list_for_each_entry(iter, flb_list, list) {
465 		if (iter->flb == flb) {
466 			list_del(&iter->list);
467 			kfree(iter);
468 			err = 0;
469 			break;
470 		}
471 	}
472 
473 	if (err)
474 		goto err_resume;
475 
476 	private->users--;
477 	/*
478 	 * If this is the last file-handler with which we are registred, remove
479 	 * from the global list, and relese module reference.
480 	 */
481 	if (!private->users) {
482 		list_del_init(&private->list);
483 		luo_flb_global.count--;
484 		module_put(flb->ops->owner);
485 	}
486 
487 	up_write(&luo_register_rwlock);
488 	luo_session_resume();
489 
490 	return 0;
491 
492 err_resume:
493 	up_write(&luo_register_rwlock);
494 	luo_session_resume();
495 	return err;
496 }
497 
498 /**
499  * liveupdate_flb_get_incoming - Retrieve the incoming FLB object.
500  * @flb:  The FLB definition.
501  * @objp: Output parameter; will be populated with the live shared object.
502  *
503  * Returns a pointer to its shared live object for the incoming (post-reboot)
504  * path.
505  *
506  * If this is the first time the object is requested in the new kernel, this
507  * function will trigger the FLB's .retrieve() callback to reconstruct the
508  * object from its preserved state. Subsequent calls will return the same
509  * cached object.
510  *
511  * Return: 0 on success, or a negative errno on failure. -ENODATA means no
512  * incoming FLB data, -ENOENT means specific flb not found in the incoming
513  * data, and -EOPNOTSUPP when live update is disabled or not configured.
514  */
515 int liveupdate_flb_get_incoming(struct liveupdate_flb *flb, void **objp)
516 {
517 	struct luo_flb_private *private = luo_flb_get_private(flb);
518 
519 	if (!liveupdate_enabled())
520 		return -EOPNOTSUPP;
521 
522 	if (!private->incoming.obj) {
523 		int err = luo_flb_retrieve_one(flb);
524 
525 		if (err)
526 			return err;
527 	}
528 
529 	guard(mutex)(&private->incoming.lock);
530 	*objp = private->incoming.obj;
531 
532 	return 0;
533 }
534 
535 /**
536  * liveupdate_flb_get_outgoing - Retrieve the outgoing FLB object.
537  * @flb:  The FLB definition.
538  * @objp: Output parameter; will be populated with the live shared object.
539  *
540  * Returns a pointer to its shared live object for the outgoing (pre-reboot)
541  * path.
542  *
543  * This function assumes the object has already been created by the FLB's
544  * .preserve() callback, which is triggered when the first dependent file
545  * is preserved.
546  *
547  * Return: 0 on success, or a negative errno on failure.
548  */
549 int liveupdate_flb_get_outgoing(struct liveupdate_flb *flb, void **objp)
550 {
551 	struct luo_flb_private *private = luo_flb_get_private(flb);
552 
553 	if (!liveupdate_enabled())
554 		return -EOPNOTSUPP;
555 
556 	guard(mutex)(&private->outgoing.lock);
557 	*objp = private->outgoing.obj;
558 
559 	return 0;
560 }
561 
562 int __init luo_flb_setup_outgoing(void *fdt_out)
563 {
564 	struct luo_flb_header_ser *header_ser;
565 	u64 header_ser_pa;
566 	int err;
567 
568 	header_ser = kho_alloc_preserve(LUO_FLB_PGCNT << PAGE_SHIFT);
569 	if (IS_ERR(header_ser))
570 		return PTR_ERR(header_ser);
571 
572 	header_ser_pa = virt_to_phys(header_ser);
573 
574 	err = fdt_begin_node(fdt_out, LUO_FDT_FLB_NODE_NAME);
575 	err |= fdt_property_string(fdt_out, "compatible",
576 				   LUO_FDT_FLB_COMPATIBLE);
577 	err |= fdt_property(fdt_out, LUO_FDT_FLB_HEADER, &header_ser_pa,
578 			    sizeof(header_ser_pa));
579 	err |= fdt_end_node(fdt_out);
580 
581 	if (err)
582 		goto err_unpreserve;
583 
584 	header_ser->pgcnt = LUO_FLB_PGCNT;
585 	luo_flb_global.outgoing.header_ser = header_ser;
586 	luo_flb_global.outgoing.ser = (void *)(header_ser + 1);
587 	luo_flb_global.outgoing.active = true;
588 
589 	return 0;
590 
591 err_unpreserve:
592 	kho_unpreserve_free(header_ser);
593 
594 	return err;
595 }
596 
597 int __init luo_flb_setup_incoming(void *fdt_in)
598 {
599 	struct luo_flb_header_ser *header_ser;
600 	int err, header_size, offset;
601 	const void *ptr;
602 	u64 header_ser_pa;
603 
604 	offset = fdt_subnode_offset(fdt_in, 0, LUO_FDT_FLB_NODE_NAME);
605 	if (offset < 0) {
606 		pr_err("Unable to get FLB node [%s]\n", LUO_FDT_FLB_NODE_NAME);
607 
608 		return -ENOENT;
609 	}
610 
611 	err = fdt_node_check_compatible(fdt_in, offset,
612 					LUO_FDT_FLB_COMPATIBLE);
613 	if (err) {
614 		pr_err("FLB node is incompatible with '%s' [%d]\n",
615 		       LUO_FDT_FLB_COMPATIBLE, err);
616 
617 		return -EINVAL;
618 	}
619 
620 	header_size = 0;
621 	ptr = fdt_getprop(fdt_in, offset, LUO_FDT_FLB_HEADER, &header_size);
622 	if (!ptr || header_size != sizeof(u64)) {
623 		pr_err("Unable to get FLB header property '%s' [%d]\n",
624 		       LUO_FDT_FLB_HEADER, header_size);
625 
626 		return -EINVAL;
627 	}
628 
629 	header_ser_pa = get_unaligned((u64 *)ptr);
630 	header_ser = phys_to_virt(header_ser_pa);
631 
632 	luo_flb_global.incoming.header_ser = header_ser;
633 	luo_flb_global.incoming.ser = (void *)(header_ser + 1);
634 	luo_flb_global.incoming.active = true;
635 
636 	return 0;
637 }
638 
639 /**
640  * luo_flb_serialize - Serializes all active FLB objects for KHO.
641  *
642  * This function is called from the reboot path. It iterates through all
643  * registered File-Lifecycle-Bound (FLB) objects. For each FLB that has been
644  * preserved (i.e., its reference count is greater than zero), it writes its
645  * metadata into the memory region designated for Kexec Handover.
646  *
647  * The serialized data includes the FLB's compatibility string, its opaque
648  * data handle, and the final reference count. This allows the new kernel to
649  * find the appropriate handler and reconstruct the FLB's state.
650  *
651  * Context: Called from liveupdate_reboot() just before kho_finalize().
652  */
653 void luo_flb_serialize(void)
654 {
655 	struct luo_flb_header *fh = &luo_flb_global.outgoing;
656 	struct liveupdate_flb *gflb;
657 	int i = 0;
658 
659 	guard(rwsem_read)(&luo_register_rwlock);
660 	list_private_for_each_entry(gflb, &luo_flb_global.list, private.list) {
661 		struct luo_flb_private *private = luo_flb_get_private(gflb);
662 
663 		if (private->outgoing.count > 0) {
664 			strscpy(fh->ser[i].name, gflb->compatible,
665 				sizeof(fh->ser[i].name));
666 			fh->ser[i].data = private->outgoing.data;
667 			fh->ser[i].count = private->outgoing.count;
668 			i++;
669 		}
670 	}
671 
672 	fh->header_ser->count = i;
673 }
674