static unsigned long copy_nonpresent_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
		pte_t *dst_pte, pte_t *src_pte, struct vm_area_struct *dst_vma,
		struct vm_area_struct *src_vma, unsigned long addr, int *rss)
{
	unsigned long vm_flags = dst_vma->vm_flags;
	pte_t orig_pte = ptep_get(src_pte);
	pte_t pte = orig_pte;
	struct folio *folio;
	struct page *page;
	swp_entry_t entry = pte_to_swp_entry(orig_pte);

	if (likely(!non_swap_entry(entry))) {
		if (swap_duplicate(entry) < 0)
			return -EIO;

		/* make sure dst_mm is on swapoff's mmlist. */
		if (unlikely(list_empty(&dst_mm->mmlist))) {
			spin_lock(&mmlist_lock);
			if (list_empty(&dst_mm->mmlist))
				list_add(&dst_mm->mmlist,
						&src_mm->mmlist);
			spin_unlock(&mmlist_lock);
		}
		/* Mark the swap entry as shared. */
		if (pte_swp_exclusive(orig_pte)) {
			pte = pte_swp_clear_exclusive(orig_pte);
			set_pte_at(src_mm, addr, src_pte, pte);
		}
		rss[MM_SWAPENTS]++;
	} else if (is_migration_entry(entry)) {
		folio = pfn_swap_entry_folio(entry);

		rss[mm_counter(folio)]++;

		if (!is_readable_migration_entry(entry) &&
				is_cow_mapping(vm_flags)) {
			/*
			 * COW mappings require pages in both parent and child
			 * to be set to read. A previously exclusive entry is
			 * now shared.
			 */
			entry = make_readable_migration_entry(
							swp_offset(entry));
			pte = swp_entry_to_pte(entry);
			if (pte_swp_soft_dirty(orig_pte))
				pte = pte_swp_mksoft_dirty(pte);
			if (pte_swp_uffd_wp(orig_pte))
				pte = pte_swp_mkuffd_wp(pte);
			set_pte_at(src_mm, addr, src_pte, pte);
		}
	} else if (is_device_private_entry(entry)) {
		page = pfn_swap_entry_to_page(entry);
		folio = page_folio(page);

		/*
		 * Update rss count even for unaddressable pages, as
		 * they should treated just like normal pages in this
		 * respect.
		 *
		 * We will likely want to have some new rss counters
		 * for unaddressable pages, at some point. But for now
		 * keep things as they are.
		 */
		folio_get(folio);
		rss[mm_counter(folio)]++;
		/* Cannot fail as these pages cannot get pinned. */
		folio_try_dup_anon_rmap_pte(folio, page, src_vma);

		/*
		 * We do not preserve soft-dirty information, because so
		 * far, checkpoint/restore is the only feature that
		 * requires that. And checkpoint/restore does not work
		 * when a device driver is involved (you cannot easily
		 * save and restore device driver state).
		 */
		if (is_writable_device_private_entry(entry) &&
		    is_cow_mapping(vm_flags)) {
			entry = make_readable_device_private_entry(
							swp_offset(entry));
			pte = swp_entry_to_pte(entry);
			if (pte_swp_uffd_wp(orig_pte))
				pte = pte_swp_mkuffd_wp(pte);
			#ifdef CONFIG_PTP
			iee_set_pte_at_delayed(src_mm, addr, src_pte, pte);
			#else
			set_pte_at(src_mm, addr, src_pte, pte);
			#endif
		}
	} else if (is_device_exclusive_entry(entry)) {
		/*
		 * Make device exclusive entries present by restoring the
		 * original entry then copying as for a present pte. Device
		 * exclusive entries currently only support private writable
		 * (ie. COW) mappings.
		 */
		VM_BUG_ON(!is_cow_mapping(src_vma->vm_flags));
		if (try_restore_exclusive_pte(src_pte, src_vma, addr))
			return -EBUSY;
		return -ENOENT;
	} else if (is_pte_marker_entry(entry)) {
		pte_marker marker = copy_pte_marker(entry, dst_vma);

		if (marker)
			#ifdef CONFIG_PTP
			iee_set_pte_at_delayed(src_mm, addr, src_pte, 
			       make_pte_marker(marker));
			#else
			set_pte_at(dst_mm, addr, dst_pte,
				   make_pte_marker(marker));
			#endif
		return false;
	}
	if (!userfaultfd_wp(dst_vma))
		pte = pte_swp_clear_uffd_wp(pte);
	#ifdef CONFIG_PTP
	iee_set_pte_at(dst_mm, addr, dst_pte, pte);
	#else
	set_pte_at(dst_mm, addr, dst_pte, pte);
	#endif
	return 0;
}