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 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 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 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 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 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 */ 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 */ 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 */ 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 */ 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(sizeof(*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 */ 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 */ 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 */ 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 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 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 */ 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