xref: /linux/kernel/liveupdate/luo_flb.c (revision e2683c8868d03382da7e1ce8453b543a043066d1)
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 			if (!try_module_get(flb->ops->owner))
119 				return -ENODEV;
120 
121 			args.flb = flb;
122 			err = flb->ops->preserve(&args);
123 			if (err) {
124 				module_put(flb->ops->owner);
125 				return err;
126 			}
127 			private->outgoing.data = args.data;
128 			private->outgoing.obj = args.obj;
129 		}
130 		private->outgoing.count++;
131 	}
132 
133 	return 0;
134 }
135 
136 static void luo_flb_file_unpreserve_one(struct liveupdate_flb *flb)
137 {
138 	struct luo_flb_private *private = luo_flb_get_private(flb);
139 
140 	scoped_guard(mutex, &private->outgoing.lock) {
141 		private->outgoing.count--;
142 		if (!private->outgoing.count) {
143 			struct liveupdate_flb_op_args args = {0};
144 
145 			args.flb = flb;
146 			args.data = private->outgoing.data;
147 			args.obj = private->outgoing.obj;
148 
149 			if (flb->ops->unpreserve)
150 				flb->ops->unpreserve(&args);
151 
152 			private->outgoing.data = 0;
153 			private->outgoing.obj = NULL;
154 			module_put(flb->ops->owner);
155 		}
156 	}
157 }
158 
159 static int luo_flb_retrieve_one(struct liveupdate_flb *flb)
160 {
161 	struct luo_flb_private *private = luo_flb_get_private(flb);
162 	struct luo_flb_header *fh = &luo_flb_global.incoming;
163 	struct liveupdate_flb_op_args args = {0};
164 	bool found = false;
165 	int err;
166 
167 	guard(mutex)(&private->incoming.lock);
168 
169 	if (private->incoming.finished)
170 		return -ENODATA;
171 
172 	if (private->incoming.retrieved)
173 		return 0;
174 
175 	if (!fh->active)
176 		return -ENODATA;
177 
178 	for (int i = 0; i < fh->header_ser->count; i++) {
179 		if (!strcmp(fh->ser[i].name, flb->compatible)) {
180 			private->incoming.data = fh->ser[i].data;
181 			private->incoming.count = fh->ser[i].count;
182 			found = true;
183 			break;
184 		}
185 	}
186 
187 	if (!found)
188 		return -ENOENT;
189 
190 	if (!try_module_get(flb->ops->owner))
191 		return -ENODEV;
192 
193 	args.flb = flb;
194 	args.data = private->incoming.data;
195 
196 	err = flb->ops->retrieve(&args);
197 	if (err) {
198 		module_put(flb->ops->owner);
199 		return err;
200 	}
201 
202 	private->incoming.obj = args.obj;
203 	private->incoming.retrieved = true;
204 
205 	return 0;
206 }
207 
208 static void luo_flb_file_finish_one(struct liveupdate_flb *flb)
209 {
210 	struct luo_flb_private *private = luo_flb_get_private(flb);
211 	u64 count;
212 
213 	scoped_guard(mutex, &private->incoming.lock)
214 		count = --private->incoming.count;
215 
216 	if (!count) {
217 		struct liveupdate_flb_op_args args = {0};
218 
219 		if (!private->incoming.retrieved) {
220 			int err = luo_flb_retrieve_one(flb);
221 
222 			if (WARN_ON(err))
223 				return;
224 		}
225 
226 		scoped_guard(mutex, &private->incoming.lock) {
227 			args.flb = flb;
228 			args.obj = private->incoming.obj;
229 			flb->ops->finish(&args);
230 
231 			private->incoming.data = 0;
232 			private->incoming.obj = NULL;
233 			private->incoming.finished = true;
234 			module_put(flb->ops->owner);
235 		}
236 	}
237 }
238 
239 /**
240  * luo_flb_file_preserve - Notifies FLBs that a file is about to be preserved.
241  * @fh: The file handler for the preserved file.
242  *
243  * This function iterates through all FLBs associated with the given file
244  * handler. It increments the reference count for each FLB. If the count becomes
245  * 1, it triggers the FLB's .preserve() callback to save the global state.
246  *
247  * This operation is atomic. If any FLB's .preserve() op fails, it will roll
248  * back by calling .unpreserve() on any FLBs that were successfully preserved
249  * during this call.
250  *
251  * Context: Called from luo_preserve_file()
252  * Return: 0 on success, or a negative errno on failure.
253  */
254 int luo_flb_file_preserve(struct liveupdate_file_handler *fh)
255 {
256 	struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list);
257 	struct luo_flb_link *iter;
258 	int err = 0;
259 
260 	down_read(&luo_register_rwlock);
261 	list_for_each_entry(iter, flb_list, list) {
262 		err = luo_flb_file_preserve_one(iter->flb);
263 		if (err)
264 			goto exit_err;
265 	}
266 	up_read(&luo_register_rwlock);
267 
268 	return 0;
269 
270 exit_err:
271 	list_for_each_entry_continue_reverse(iter, flb_list, list)
272 		luo_flb_file_unpreserve_one(iter->flb);
273 	up_read(&luo_register_rwlock);
274 
275 	return err;
276 }
277 
278 /**
279  * luo_flb_file_unpreserve - Notifies FLBs that a dependent file was unpreserved.
280  * @fh: The file handler for the unpreserved file.
281  *
282  * This function iterates through all FLBs associated with the given file
283  * handler, in reverse order of registration. It decrements the reference count
284  * for each FLB. If the count becomes 0, it triggers the FLB's .unpreserve()
285  * callback to clean up the global state.
286  *
287  * Context: Called when a preserved file is being cleaned up before reboot
288  *          (e.g., from luo_file_unpreserve_files()).
289  */
290 void luo_flb_file_unpreserve(struct liveupdate_file_handler *fh)
291 {
292 	struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list);
293 	struct luo_flb_link *iter;
294 
295 	guard(rwsem_read)(&luo_register_rwlock);
296 	list_for_each_entry_reverse(iter, flb_list, list)
297 		luo_flb_file_unpreserve_one(iter->flb);
298 }
299 
300 /**
301  * luo_flb_file_finish - Notifies FLBs that a dependent file has been finished.
302  * @fh: The file handler for the finished file.
303  *
304  * This function iterates through all FLBs associated with the given file
305  * handler, in reverse order of registration. It decrements the incoming
306  * reference count for each FLB. If the count becomes 0, it triggers the FLB's
307  * .finish() callback for final cleanup in the new kernel.
308  *
309  * Context: Called from luo_file_finish() for each file being finished.
310  */
311 void luo_flb_file_finish(struct liveupdate_file_handler *fh)
312 {
313 	struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list);
314 	struct luo_flb_link *iter;
315 
316 	guard(rwsem_read)(&luo_register_rwlock);
317 	list_for_each_entry_reverse(iter, flb_list, list)
318 		luo_flb_file_finish_one(iter->flb);
319 }
320 
321 static void luo_flb_unregister_one(struct liveupdate_file_handler *fh,
322 				   struct liveupdate_flb *flb)
323 {
324 	struct luo_flb_private *private = luo_flb_get_private(flb);
325 	struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list);
326 	struct luo_flb_link *iter;
327 	bool found = false;
328 
329 	/* Find and remove the link from the file handler's list */
330 	list_for_each_entry(iter, flb_list, list) {
331 		if (iter->flb == flb) {
332 			list_del(&iter->list);
333 			kfree(iter);
334 			found = true;
335 			break;
336 		}
337 	}
338 
339 	if (!found) {
340 		pr_warn("Failed to unregister FLB '%s': not found in file handler '%s'\n",
341 			flb->compatible, fh->compatible);
342 		return;
343 	}
344 
345 	private->users--;
346 
347 	/*
348 	 * If this is the last file-handler with which we are registred, remove
349 	 * from the global list.
350 	 */
351 	if (!private->users) {
352 		list_del_init(&private->list);
353 		luo_flb_global.count--;
354 	}
355 }
356 
357 /**
358  * luo_flb_unregister_all - Unregister all FLBs associated with a file handler.
359  * @fh: The file handler whose FLBs should be unregistered.
360  *
361  * This function iterates through the list of FLBs associated with the given
362  * file handler and unregisters them all one by one.
363  */
364 void luo_flb_unregister_all(struct liveupdate_file_handler *fh)
365 {
366 	struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list);
367 	struct luo_flb_link *iter, *tmp;
368 
369 	if (!liveupdate_enabled())
370 		return;
371 
372 	lockdep_assert_held_write(&luo_register_rwlock);
373 	list_for_each_entry_safe(iter, tmp, flb_list, list)
374 		luo_flb_unregister_one(fh, iter->flb);
375 }
376 
377 /**
378  * liveupdate_register_flb - Associate an FLB with a file handler and register it globally.
379  * @fh:   The file handler that will now depend on the FLB.
380  * @flb:  The File-Lifecycle-Bound object to associate.
381  *
382  * Establishes a dependency, informing the LUO core that whenever a file of
383  * type @fh is preserved, the state of @flb must also be managed.
384  *
385  * On the first registration of a given @flb object, it is added to a global
386  * registry. This function checks for duplicate registrations, both for a
387  * specific handler and globally, and ensures the total number of unique
388  * FLBs does not exceed the system limit.
389  *
390  * Context: Typically called from a subsystem's module init function after
391  *          both the handler and the FLB have been defined and initialized.
392  * Return: 0 on success. Returns a negative errno on failure:
393  *         -EINVAL if arguments are NULL or not initialized.
394  *         -ENOMEM on memory allocation failure.
395  *         -EEXIST if this FLB is already registered with this handler.
396  *         -ENOSPC if the maximum number of global FLBs has been reached.
397  *         -EOPNOTSUPP if live update is disabled or not configured.
398  */
399 int liveupdate_register_flb(struct liveupdate_file_handler *fh,
400 			    struct liveupdate_flb *flb)
401 {
402 	struct luo_flb_private *private = luo_flb_get_private(flb);
403 	struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list);
404 	struct luo_flb_link *link __free(kfree) = NULL;
405 	struct liveupdate_flb *gflb;
406 	struct luo_flb_link *iter;
407 
408 	if (!liveupdate_enabled())
409 		return -EOPNOTSUPP;
410 
411 	if (WARN_ON(!flb->ops->preserve || !flb->ops->unpreserve ||
412 		    !flb->ops->retrieve || !flb->ops->finish)) {
413 		return -EINVAL;
414 	}
415 
416 	/*
417 	 * File handler must already be registered, as it initializes the
418 	 * flb_list
419 	 */
420 	if (WARN_ON(list_empty(&ACCESS_PRIVATE(fh, list))))
421 		return -EINVAL;
422 
423 	link = kzalloc_obj(*link);
424 	if (!link)
425 		return -ENOMEM;
426 
427 	guard(rwsem_write)(&luo_register_rwlock);
428 
429 	/* Check that this FLB is not already linked to this file handler */
430 	list_for_each_entry(iter, flb_list, list) {
431 		if (iter->flb == flb)
432 			return -EEXIST;
433 	}
434 
435 	/*
436 	 * If this FLB is not linked to global list it's the first time the FLB
437 	 * is registered
438 	 */
439 	if (!private->users) {
440 		if (WARN_ON(!list_empty(&private->list)))
441 			return -EINVAL;
442 
443 		if (luo_flb_global.count == LUO_FLB_MAX)
444 			return -ENOSPC;
445 
446 		/* Check that compatible string is unique in global list */
447 		list_private_for_each_entry(gflb, &luo_flb_global.list, private.list) {
448 			if (!strcmp(gflb->compatible, flb->compatible))
449 				return -EEXIST;
450 		}
451 
452 		list_add_tail(&private->list, &luo_flb_global.list);
453 		luo_flb_global.count++;
454 	}
455 
456 	/* Finally, link the FLB to the file handler */
457 	private->users++;
458 	link->flb = flb;
459 	list_add_tail(&no_free_ptr(link)->list, flb_list);
460 
461 	return 0;
462 }
463 
464 /**
465  * liveupdate_unregister_flb - Remove an FLB dependency from a file handler.
466  * @fh:   The file handler that is currently depending on the FLB.
467  * @flb:  The File-Lifecycle-Bound object to remove.
468  *
469  * Removes the association between the specified file handler and the FLB
470  * previously established by liveupdate_register_flb().
471  *
472  * This function manages the global lifecycle of the FLB. It decrements the
473  * FLB's usage count. If this was the last file handler referencing this FLB,
474  * the FLB is removed from the global registry and the reference to its
475  * owner module (acquired during registration) is released.
476  *
477  * Context: It is typically called from a subsystem's module exit function.
478  */
479 void liveupdate_unregister_flb(struct liveupdate_file_handler *fh,
480 			       struct liveupdate_flb *flb)
481 {
482 	if (!liveupdate_enabled())
483 		return;
484 
485 	guard(rwsem_write)(&luo_register_rwlock);
486 
487 	luo_flb_unregister_one(fh, flb);
488 }
489 
490 /**
491  * liveupdate_flb_get_incoming - Retrieve the incoming FLB object.
492  * @flb:  The FLB definition.
493  * @objp: Output parameter; will be populated with the live shared object.
494  *
495  * Returns a pointer to its shared live object for the incoming (post-reboot)
496  * path.
497  *
498  * If this is the first time the object is requested in the new kernel, this
499  * function will trigger the FLB's .retrieve() callback to reconstruct the
500  * object from its preserved state. Subsequent calls will return the same
501  * cached object.
502  *
503  * Return: 0 on success, or a negative errno on failure. -ENODATA means no
504  * incoming FLB data, -ENOENT means specific flb not found in the incoming
505  * data, -ENODEV if the FLB's module is unloading, and -EOPNOTSUPP when
506  * live update is disabled or not configured.
507  */
508 int liveupdate_flb_get_incoming(struct liveupdate_flb *flb, void **objp)
509 {
510 	struct luo_flb_private *private = luo_flb_get_private(flb);
511 
512 	if (!liveupdate_enabled())
513 		return -EOPNOTSUPP;
514 
515 	if (!private->incoming.obj) {
516 		int err = luo_flb_retrieve_one(flb);
517 
518 		if (err)
519 			return err;
520 	}
521 
522 	guard(mutex)(&private->incoming.lock);
523 	*objp = private->incoming.obj;
524 
525 	return 0;
526 }
527 
528 /**
529  * liveupdate_flb_get_outgoing - Retrieve the outgoing FLB object.
530  * @flb:  The FLB definition.
531  * @objp: Output parameter; will be populated with the live shared object.
532  *
533  * Returns a pointer to its shared live object for the outgoing (pre-reboot)
534  * path.
535  *
536  * This function assumes the object has already been created by the FLB's
537  * .preserve() callback, which is triggered when the first dependent file
538  * is preserved.
539  *
540  * Return: 0 on success, or a negative errno on failure.
541  */
542 int liveupdate_flb_get_outgoing(struct liveupdate_flb *flb, void **objp)
543 {
544 	struct luo_flb_private *private = luo_flb_get_private(flb);
545 
546 	if (!liveupdate_enabled())
547 		return -EOPNOTSUPP;
548 
549 	guard(mutex)(&private->outgoing.lock);
550 	*objp = private->outgoing.obj;
551 
552 	return 0;
553 }
554 
555 int __init luo_flb_setup_outgoing(void *fdt_out)
556 {
557 	struct luo_flb_header_ser *header_ser;
558 	u64 header_ser_pa;
559 	int err;
560 
561 	header_ser = kho_alloc_preserve(LUO_FLB_PGCNT << PAGE_SHIFT);
562 	if (IS_ERR(header_ser))
563 		return PTR_ERR(header_ser);
564 
565 	header_ser_pa = virt_to_phys(header_ser);
566 
567 	err = fdt_begin_node(fdt_out, LUO_FDT_FLB_NODE_NAME);
568 	err |= fdt_property_string(fdt_out, "compatible",
569 				   LUO_FDT_FLB_COMPATIBLE);
570 	err |= fdt_property(fdt_out, LUO_FDT_FLB_HEADER, &header_ser_pa,
571 			    sizeof(header_ser_pa));
572 	err |= fdt_end_node(fdt_out);
573 
574 	if (err)
575 		goto err_unpreserve;
576 
577 	header_ser->pgcnt = LUO_FLB_PGCNT;
578 	luo_flb_global.outgoing.header_ser = header_ser;
579 	luo_flb_global.outgoing.ser = (void *)(header_ser + 1);
580 	luo_flb_global.outgoing.active = true;
581 
582 	return 0;
583 
584 err_unpreserve:
585 	kho_unpreserve_free(header_ser);
586 
587 	return err;
588 }
589 
590 int __init luo_flb_setup_incoming(void *fdt_in)
591 {
592 	struct luo_flb_header_ser *header_ser;
593 	int err, header_size, offset;
594 	const void *ptr;
595 	u64 header_ser_pa;
596 
597 	offset = fdt_subnode_offset(fdt_in, 0, LUO_FDT_FLB_NODE_NAME);
598 	if (offset < 0) {
599 		pr_err("Unable to get FLB node [%s]\n", LUO_FDT_FLB_NODE_NAME);
600 
601 		return -ENOENT;
602 	}
603 
604 	err = fdt_node_check_compatible(fdt_in, offset,
605 					LUO_FDT_FLB_COMPATIBLE);
606 	if (err) {
607 		pr_err("FLB node is incompatible with '%s' [%d]\n",
608 		       LUO_FDT_FLB_COMPATIBLE, err);
609 
610 		return -EINVAL;
611 	}
612 
613 	header_size = 0;
614 	ptr = fdt_getprop(fdt_in, offset, LUO_FDT_FLB_HEADER, &header_size);
615 	if (!ptr || header_size != sizeof(u64)) {
616 		pr_err("Unable to get FLB header property '%s' [%d]\n",
617 		       LUO_FDT_FLB_HEADER, header_size);
618 
619 		return -EINVAL;
620 	}
621 
622 	header_ser_pa = get_unaligned((u64 *)ptr);
623 	header_ser = phys_to_virt(header_ser_pa);
624 
625 	luo_flb_global.incoming.header_ser = header_ser;
626 	luo_flb_global.incoming.ser = (void *)(header_ser + 1);
627 	luo_flb_global.incoming.active = true;
628 
629 	return 0;
630 }
631 
632 /**
633  * luo_flb_serialize - Serializes all active FLB objects for KHO.
634  *
635  * This function is called from the reboot path. It iterates through all
636  * registered File-Lifecycle-Bound (FLB) objects. For each FLB that has been
637  * preserved (i.e., its reference count is greater than zero), it writes its
638  * metadata into the memory region designated for Kexec Handover.
639  *
640  * The serialized data includes the FLB's compatibility string, its opaque
641  * data handle, and the final reference count. This allows the new kernel to
642  * find the appropriate handler and reconstruct the FLB's state.
643  *
644  * Context: Called from liveupdate_reboot() just before kho_finalize().
645  */
646 void luo_flb_serialize(void)
647 {
648 	struct luo_flb_header *fh = &luo_flb_global.outgoing;
649 	struct liveupdate_flb *gflb;
650 	int i = 0;
651 
652 	guard(rwsem_read)(&luo_register_rwlock);
653 	list_private_for_each_entry(gflb, &luo_flb_global.list, private.list) {
654 		struct luo_flb_private *private = luo_flb_get_private(gflb);
655 
656 		if (private->outgoing.count > 0) {
657 			strscpy(fh->ser[i].name, gflb->compatible,
658 				sizeof(fh->ser[i].name));
659 			fh->ser[i].data = private->outgoing.data;
660 			fh->ser[i].count = private->outgoing.count;
661 			i++;
662 		}
663 	}
664 
665 	fh->header_ser->count = i;
666 }
667