copypage.c 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Based on arch/arm/mm/copypage.c
  4. *
  5. * Copyright (C) 2002 Deep Blue Solutions Ltd, All Rights Reserved.
  6. * Copyright (C) 2012 ARM Ltd.
  7. */
  8. #include <linux/bitops.h>
  9. #include <linux/mm.h>
  10. #include <asm/page.h>
  11. #include <asm/cacheflush.h>
  12. #include <asm/cpufeature.h>
  13. #include <asm/mte.h>
  14. void copy_highpage(struct page *to, struct page *from)
  15. {
  16. void *kto = page_address(to);
  17. void *kfrom = page_address(from);
  18. struct folio *src = page_folio(from);
  19. struct folio *dst = page_folio(to);
  20. unsigned int i, nr_pages;
  21. copy_page(kto, kfrom);
  22. if (kasan_hw_tags_enabled())
  23. page_kasan_tag_reset(to);
  24. if (!system_supports_mte())
  25. return;
  26. if (folio_test_hugetlb(src)) {
  27. if (!folio_test_hugetlb_mte_tagged(src) ||
  28. from != folio_page(src, 0))
  29. return;
  30. folio_try_hugetlb_mte_tagging(dst);
  31. /*
  32. * Populate tags for all subpages.
  33. *
  34. * Don't assume the first page is head page since
  35. * huge page copy may start from any subpage.
  36. */
  37. nr_pages = folio_nr_pages(src);
  38. for (i = 0; i < nr_pages; i++) {
  39. kfrom = page_address(folio_page(src, i));
  40. kto = page_address(folio_page(dst, i));
  41. mte_copy_page_tags(kto, kfrom);
  42. }
  43. folio_set_hugetlb_mte_tagged(dst);
  44. } else if (page_mte_tagged(from)) {
  45. /*
  46. * Most of the time it's a new page that shouldn't have been
  47. * tagged yet. However, folio migration can end up reusing the
  48. * same page without untagging it. Ignore the warning if the
  49. * page is already tagged.
  50. */
  51. try_page_mte_tagging(to);
  52. mte_copy_page_tags(kto, kfrom);
  53. set_page_mte_tagged(to);
  54. }
  55. }
  56. EXPORT_SYMBOL(copy_highpage);
  57. void copy_user_highpage(struct page *to, struct page *from,
  58. unsigned long vaddr, struct vm_area_struct *vma)
  59. {
  60. copy_highpage(to, from);
  61. flush_dcache_page(to);
  62. }
  63. EXPORT_SYMBOL_GPL(copy_user_highpage);