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