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