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