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 list_for_each_entry(iter, flb_list, list) { 249 err = luo_flb_file_preserve_one(iter->flb); 250 if (err) 251 goto exit_err; 252 } 253 254 return 0; 255 256 exit_err: 257 list_for_each_entry_continue_reverse(iter, flb_list, list) 258 luo_flb_file_unpreserve_one(iter->flb); 259 260 return err; 261 } 262 263 /** 264 * luo_flb_file_unpreserve - Notifies FLBs that a dependent file was unpreserved. 265 * @fh: The file handler for the unpreserved file. 266 * 267 * This function iterates through all FLBs associated with the given file 268 * handler, in reverse order of registration. It decrements the reference count 269 * for each FLB. If the count becomes 0, it triggers the FLB's .unpreserve() 270 * callback to clean up the global state. 271 * 272 * Context: Called when a preserved file is being cleaned up before reboot 273 * (e.g., from luo_file_unpreserve_files()). 274 */ 275 void luo_flb_file_unpreserve(struct liveupdate_file_handler *fh) 276 { 277 struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list); 278 struct luo_flb_link *iter; 279 280 list_for_each_entry_reverse(iter, flb_list, list) 281 luo_flb_file_unpreserve_one(iter->flb); 282 } 283 284 /** 285 * luo_flb_file_finish - Notifies FLBs that a dependent file has been finished. 286 * @fh: The file handler for the finished file. 287 * 288 * This function iterates through all FLBs associated with the given file 289 * handler, in reverse order of registration. It decrements the incoming 290 * reference count for each FLB. If the count becomes 0, it triggers the FLB's 291 * .finish() callback for final cleanup in the new kernel. 292 * 293 * Context: Called from luo_file_finish() for each file being finished. 294 */ 295 void luo_flb_file_finish(struct liveupdate_file_handler *fh) 296 { 297 struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list); 298 struct luo_flb_link *iter; 299 300 list_for_each_entry_reverse(iter, flb_list, list) 301 luo_flb_file_finish_one(iter->flb); 302 } 303 304 /** 305 * liveupdate_register_flb - Associate an FLB with a file handler and register it globally. 306 * @fh: The file handler that will now depend on the FLB. 307 * @flb: The File-Lifecycle-Bound object to associate. 308 * 309 * Establishes a dependency, informing the LUO core that whenever a file of 310 * type @fh is preserved, the state of @flb must also be managed. 311 * 312 * On the first registration of a given @flb object, it is added to a global 313 * registry. This function checks for duplicate registrations, both for a 314 * specific handler and globally, and ensures the total number of unique 315 * FLBs does not exceed the system limit. 316 * 317 * Context: Typically called from a subsystem's module init function after 318 * both the handler and the FLB have been defined and initialized. 319 * Return: 0 on success. Returns a negative errno on failure: 320 * -EINVAL if arguments are NULL or not initialized. 321 * -ENOMEM on memory allocation failure. 322 * -EEXIST if this FLB is already registered with this handler. 323 * -ENOSPC if the maximum number of global FLBs has been reached. 324 * -EOPNOTSUPP if live update is disabled or not configured. 325 */ 326 int liveupdate_register_flb(struct liveupdate_file_handler *fh, 327 struct liveupdate_flb *flb) 328 { 329 struct luo_flb_private *private = luo_flb_get_private(flb); 330 struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list); 331 struct luo_flb_link *link __free(kfree) = NULL; 332 struct liveupdate_flb *gflb; 333 struct luo_flb_link *iter; 334 int err; 335 336 if (!liveupdate_enabled()) 337 return -EOPNOTSUPP; 338 339 if (WARN_ON(!flb->ops->preserve || !flb->ops->unpreserve || 340 !flb->ops->retrieve || !flb->ops->finish)) { 341 return -EINVAL; 342 } 343 344 /* 345 * File handler must already be registered, as it initializes the 346 * flb_list 347 */ 348 if (WARN_ON(list_empty(&ACCESS_PRIVATE(fh, list)))) 349 return -EINVAL; 350 351 link = kzalloc_obj(*link); 352 if (!link) 353 return -ENOMEM; 354 355 /* 356 * Ensure the system is quiescent (no active sessions). 357 * This acts as a global lock for registration: no other thread can 358 * be in this section, and no sessions can be creating/using FDs. 359 */ 360 if (!luo_session_quiesce()) 361 return -EBUSY; 362 363 /* Check that this FLB is not already linked to this file handler */ 364 err = -EEXIST; 365 list_for_each_entry(iter, flb_list, list) { 366 if (iter->flb == flb) 367 goto err_resume; 368 } 369 370 /* 371 * If this FLB is not linked to global list it's the first time the FLB 372 * is registered 373 */ 374 if (!private->users) { 375 if (WARN_ON(!list_empty(&private->list))) { 376 err = -EINVAL; 377 goto err_resume; 378 } 379 380 if (luo_flb_global.count == LUO_FLB_MAX) { 381 err = -ENOSPC; 382 goto err_resume; 383 } 384 385 /* Check that compatible string is unique in global list */ 386 list_private_for_each_entry(gflb, &luo_flb_global.list, private.list) { 387 if (!strcmp(gflb->compatible, flb->compatible)) 388 goto err_resume; 389 } 390 391 if (!try_module_get(flb->ops->owner)) { 392 err = -EAGAIN; 393 goto err_resume; 394 } 395 396 list_add_tail(&private->list, &luo_flb_global.list); 397 luo_flb_global.count++; 398 } 399 400 /* Finally, link the FLB to the file handler */ 401 private->users++; 402 link->flb = flb; 403 list_add_tail(&no_free_ptr(link)->list, flb_list); 404 luo_session_resume(); 405 406 return 0; 407 408 err_resume: 409 luo_session_resume(); 410 return err; 411 } 412 413 /** 414 * liveupdate_unregister_flb - Remove an FLB dependency from a file handler. 415 * @fh: The file handler that is currently depending on the FLB. 416 * @flb: The File-Lifecycle-Bound object to remove. 417 * 418 * Removes the association between the specified file handler and the FLB 419 * previously established by liveupdate_register_flb(). 420 * 421 * This function manages the global lifecycle of the FLB. It decrements the 422 * FLB's usage count. If this was the last file handler referencing this FLB, 423 * the FLB is removed from the global registry and the reference to its 424 * owner module (acquired during registration) is released. 425 * 426 * Context: This function ensures the session is quiesced (no active FDs 427 * being created) during the update. It is typically called from a 428 * subsystem's module exit function. 429 * Return: 0 on success. 430 * -EOPNOTSUPP if live update is disabled. 431 * -EBUSY if the live update session is active and cannot be quiesced. 432 * -ENOENT if the FLB was not found in the file handler's list. 433 */ 434 int liveupdate_unregister_flb(struct liveupdate_file_handler *fh, 435 struct liveupdate_flb *flb) 436 { 437 struct luo_flb_private *private = luo_flb_get_private(flb); 438 struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list); 439 struct luo_flb_link *iter; 440 int err = -ENOENT; 441 442 if (!liveupdate_enabled()) 443 return -EOPNOTSUPP; 444 445 /* 446 * Ensure the system is quiescent (no active sessions). 447 * This acts as a global lock for unregistration. 448 */ 449 if (!luo_session_quiesce()) 450 return -EBUSY; 451 452 /* Find and remove the link from the file handler's list */ 453 list_for_each_entry(iter, flb_list, list) { 454 if (iter->flb == flb) { 455 list_del(&iter->list); 456 kfree(iter); 457 err = 0; 458 break; 459 } 460 } 461 462 if (err) 463 goto err_resume; 464 465 private->users--; 466 /* 467 * If this is the last file-handler with which we are registred, remove 468 * from the global list, and relese module reference. 469 */ 470 if (!private->users) { 471 list_del_init(&private->list); 472 luo_flb_global.count--; 473 module_put(flb->ops->owner); 474 } 475 476 luo_session_resume(); 477 478 return 0; 479 480 err_resume: 481 luo_session_resume(); 482 return err; 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, and -EOPNOTSUPP when live update is disabled or not configured. 501 */ 502 int liveupdate_flb_get_incoming(struct liveupdate_flb *flb, void **objp) 503 { 504 struct luo_flb_private *private = luo_flb_get_private(flb); 505 506 if (!liveupdate_enabled()) 507 return -EOPNOTSUPP; 508 509 if (!private->incoming.obj) { 510 int err = luo_flb_retrieve_one(flb); 511 512 if (err) 513 return err; 514 } 515 516 guard(mutex)(&private->incoming.lock); 517 *objp = private->incoming.obj; 518 519 return 0; 520 } 521 522 /** 523 * liveupdate_flb_get_outgoing - Retrieve the outgoing FLB object. 524 * @flb: The FLB definition. 525 * @objp: Output parameter; will be populated with the live shared object. 526 * 527 * Returns a pointer to its shared live object for the outgoing (pre-reboot) 528 * path. 529 * 530 * This function assumes the object has already been created by the FLB's 531 * .preserve() callback, which is triggered when the first dependent file 532 * is preserved. 533 * 534 * Return: 0 on success, or a negative errno on failure. 535 */ 536 int liveupdate_flb_get_outgoing(struct liveupdate_flb *flb, void **objp) 537 { 538 struct luo_flb_private *private = luo_flb_get_private(flb); 539 540 if (!liveupdate_enabled()) 541 return -EOPNOTSUPP; 542 543 guard(mutex)(&private->outgoing.lock); 544 *objp = private->outgoing.obj; 545 546 return 0; 547 } 548 549 int __init luo_flb_setup_outgoing(void *fdt_out) 550 { 551 struct luo_flb_header_ser *header_ser; 552 u64 header_ser_pa; 553 int err; 554 555 header_ser = kho_alloc_preserve(LUO_FLB_PGCNT << PAGE_SHIFT); 556 if (IS_ERR(header_ser)) 557 return PTR_ERR(header_ser); 558 559 header_ser_pa = virt_to_phys(header_ser); 560 561 err = fdt_begin_node(fdt_out, LUO_FDT_FLB_NODE_NAME); 562 err |= fdt_property_string(fdt_out, "compatible", 563 LUO_FDT_FLB_COMPATIBLE); 564 err |= fdt_property(fdt_out, LUO_FDT_FLB_HEADER, &header_ser_pa, 565 sizeof(header_ser_pa)); 566 err |= fdt_end_node(fdt_out); 567 568 if (err) 569 goto err_unpreserve; 570 571 header_ser->pgcnt = LUO_FLB_PGCNT; 572 luo_flb_global.outgoing.header_ser = header_ser; 573 luo_flb_global.outgoing.ser = (void *)(header_ser + 1); 574 luo_flb_global.outgoing.active = true; 575 576 return 0; 577 578 err_unpreserve: 579 kho_unpreserve_free(header_ser); 580 581 return err; 582 } 583 584 int __init luo_flb_setup_incoming(void *fdt_in) 585 { 586 struct luo_flb_header_ser *header_ser; 587 int err, header_size, offset; 588 const void *ptr; 589 u64 header_ser_pa; 590 591 offset = fdt_subnode_offset(fdt_in, 0, LUO_FDT_FLB_NODE_NAME); 592 if (offset < 0) { 593 pr_err("Unable to get FLB node [%s]\n", LUO_FDT_FLB_NODE_NAME); 594 595 return -ENOENT; 596 } 597 598 err = fdt_node_check_compatible(fdt_in, offset, 599 LUO_FDT_FLB_COMPATIBLE); 600 if (err) { 601 pr_err("FLB node is incompatible with '%s' [%d]\n", 602 LUO_FDT_FLB_COMPATIBLE, err); 603 604 return -EINVAL; 605 } 606 607 header_size = 0; 608 ptr = fdt_getprop(fdt_in, offset, LUO_FDT_FLB_HEADER, &header_size); 609 if (!ptr || header_size != sizeof(u64)) { 610 pr_err("Unable to get FLB header property '%s' [%d]\n", 611 LUO_FDT_FLB_HEADER, header_size); 612 613 return -EINVAL; 614 } 615 616 header_ser_pa = get_unaligned((u64 *)ptr); 617 header_ser = phys_to_virt(header_ser_pa); 618 619 luo_flb_global.incoming.header_ser = header_ser; 620 luo_flb_global.incoming.ser = (void *)(header_ser + 1); 621 luo_flb_global.incoming.active = true; 622 623 return 0; 624 } 625 626 /** 627 * luo_flb_serialize - Serializes all active FLB objects for KHO. 628 * 629 * This function is called from the reboot path. It iterates through all 630 * registered File-Lifecycle-Bound (FLB) objects. For each FLB that has been 631 * preserved (i.e., its reference count is greater than zero), it writes its 632 * metadata into the memory region designated for Kexec Handover. 633 * 634 * The serialized data includes the FLB's compatibility string, its opaque 635 * data handle, and the final reference count. This allows the new kernel to 636 * find the appropriate handler and reconstruct the FLB's state. 637 * 638 * Context: Called from liveupdate_reboot() just before kho_finalize(). 639 */ 640 void luo_flb_serialize(void) 641 { 642 struct luo_flb_header *fh = &luo_flb_global.outgoing; 643 struct liveupdate_flb *gflb; 644 int i = 0; 645 646 list_private_for_each_entry(gflb, &luo_flb_global.list, private.list) { 647 struct luo_flb_private *private = luo_flb_get_private(gflb); 648 649 if (private->outgoing.count > 0) { 650 strscpy(fh->ser[i].name, gflb->compatible, 651 sizeof(fh->ser[i].name)); 652 fh->ser[i].data = private->outgoing.data; 653 fh->ser[i].count = private->outgoing.count; 654 i++; 655 } 656 } 657 658 fh->header_ser->count = i; 659 } 660