mteswap.c 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. #include <linux/pagemap.h>
  3. #include <linux/xarray.h>
  4. #include <linux/slab.h>
  5. #include <linux/swap.h>
  6. #include <linux/swapops.h>
  7. #include <asm/mte.h>
  8. static DEFINE_XARRAY(mte_pages);
  9. void *mte_allocate_tag_storage(void)
  10. {
  11. /* tags granule is 16 bytes, 2 tags stored per byte */
  12. return kmalloc(MTE_PAGE_TAG_STORAGE, GFP_KERNEL);
  13. }
  14. void mte_free_tag_storage(char *storage)
  15. {
  16. kfree(storage);
  17. }
  18. int mte_save_tags(struct page *page)
  19. {
  20. void *tag_storage, *ret;
  21. if (!page_mte_tagged(page))
  22. return 0;
  23. tag_storage = mte_allocate_tag_storage();
  24. if (!tag_storage)
  25. return -ENOMEM;
  26. mte_save_page_tags(page_address(page), tag_storage);
  27. /* page_private contains the swap entry.val set in do_swap_page */
  28. ret = xa_store(&mte_pages, page_private(page), tag_storage, GFP_KERNEL);
  29. if (WARN(xa_is_err(ret), "Failed to store MTE tags")) {
  30. mte_free_tag_storage(tag_storage);
  31. return xa_err(ret);
  32. } else if (ret) {
  33. /* Entry is being replaced, free the old entry */
  34. mte_free_tag_storage(ret);
  35. }
  36. return 0;
  37. }
  38. void mte_restore_tags(swp_entry_t entry, struct page *page)
  39. {
  40. void *tags = xa_load(&mte_pages, entry.val);
  41. if (!tags)
  42. return;
  43. /*
  44. * Test PG_mte_tagged in case the tags were restored before
  45. * (e.g. CoW pages).
  46. */
  47. if (!test_and_set_bit(PG_mte_tagged, &page->flags))
  48. mte_restore_page_tags(page_address(page), tags);
  49. }
  50. void mte_invalidate_tags(int type, pgoff_t offset)
  51. {
  52. swp_entry_t entry = swp_entry(type, offset);
  53. void *tags = xa_erase(&mte_pages, entry.val);
  54. mte_free_tag_storage(tags);
  55. }
  56. void mte_invalidate_tags_area(int type)
  57. {
  58. swp_entry_t entry = swp_entry(type, 0);
  59. swp_entry_t last_entry = swp_entry(type + 1, 0);
  60. void *tags;
  61. XA_STATE(xa_state, &mte_pages, entry.val);
  62. xa_lock(&mte_pages);
  63. xas_for_each(&xa_state, tags, last_entry.val - 1) {
  64. __xa_erase(&mte_pages, xa_state.xa_index);
  65. mte_free_tag_storage(tags);
  66. }
  67. xa_unlock(&mte_pages);
  68. }