FreeBSD/sys/arm64/arm64/pmap.c
/**
 * Get the kernel virtual address of a set of physical pages. If there are
 * physical addresses not covered by the DMAP perform a transient mapping
 * that will be removed when calling pmap_unmap_io_transient.
 *
 * \param page        The pages the caller wishes to obtain the virtual
 *                    address on the kernel memory map.
 * \param vaddr       On return contains the kernel virtual memory address
 *                    of the pages passed in the page parameter.
 * \param count       Number of pages passed in.
 * \param can_fault   TRUE if the thread using the mapped pages can take
 *                    page faults, FALSE otherwise.
 *
 * \returns TRUE if the caller must call pmap_unmap_io_transient when
 *          finished or FALSE otherwise.
 *
 */
Get the kernel virtual address of a set of physical pages. If there are
physical addresses not covered by the DMAP perform a transient mapping
that will be removed when calling pmap_unmap_io_transient.

\param page        The pages the caller wishes to obtain the virtual
address on the kernel memory map.
\param vaddr       On return contains the kernel virtual memory address
of the pages passed in the page parameter.
\param count       Number of pages passed in.
\param can_fault   TRUE if the thread using the mapped pages can take
page faults, FALSE otherwise.

\returns TRUE if the caller must call pmap_unmap_io_transient when
finished or FALSE otherwise.
Get the kernel virtual address of a set of physical pages . If there are physical addresses not covered by the DMAP perform a transient mapping that will be removed when calling pmap_unmap_io_transient . \ param page The pages the caller wishes to obtain the virtual address on the kernel memory map . \ param vaddr On return contains the kernel virtual memory address of the pages passed in the page parameter . \ param count Number of pages passed in . \ param can_fault TRUE if the thread using the mapped pages can take page faults FALSE otherwise . \ returns TRUE if the caller must call pmap_unmap_io_transient when finished or FALSE otherwise .
boolean_t
pmap_map_io_transient(vm_page_t page[], vm_offset_t vaddr[], int count,
    boolean_t can_fault)
{
	vm_paddr_t paddr;
	boolean_t needs_mapping;
	int error, i;
	needs_mapping = FALSE;
	for (i = 0; i < count; i++) {
		paddr = VM_PAGE_TO_PHYS(page[i]);
		if (__predict_false(!PHYS_IN_DMAP(paddr))) {
			error = vmem_alloc(kernel_arena, PAGE_SIZE,
			    M_BESTFIT | M_WAITOK, &vaddr[i]);
			KASSERT(error == 0, ("vmem_alloc failed: %d", error));
			needs_mapping = TRUE;
		} else {
			vaddr[i] = PHYS_TO_DMAP(paddr);
		}
	}
	if (!needs_mapping)
		return (FALSE);
	if (!can_fault)
		sched_pin();
	for (i = 0; i < count; i++) {
		paddr = VM_PAGE_TO_PHYS(page[i]);
		if (!PHYS_IN_DMAP(paddr)) {
			panic(
			   "pmap_map_io_transient: TODO: Map out of DMAP data");
		}
	}
	return (needs_mapping);
}
boolean_t pmap_map_io_transient ( vm_page_t page [ ] , vm_offset_t vaddr [ ] , int count , boolean_t can_fault ) { vm_paddr_t paddr ; boolean_t needs_mapping ; int error , i ; needs_mapping = FALSE ; for ( i = 0 ; i < count ; i ++ ) { paddr = VM_PAGE_TO_PHYS ( page [ i ] ) ; if ( __predict_false ( ! PHYS_IN_DMAP ( paddr ) ) ) { error = vmem_alloc ( kernel_arena , PAGE_SIZE , M_BESTFIT | M_WAITOK , & vaddr [ i ] ) ; KASSERT ( error == 0 , ( " " , error ) ) ; needs_mapping = TRUE ; } else { vaddr [ i ] = PHYS_TO_DMAP ( paddr ) ; } } if ( ! needs_mapping ) return ( FALSE ) ; if ( ! can_fault ) sched_pin ( ) ; for ( i = 0 ; i < count ; i ++ ) { paddr = VM_PAGE_TO_PHYS ( page [ i ] ) ; if ( ! PHYS_IN_DMAP ( paddr ) ) { panic ( " " ) ; } } return ( needs_mapping ) ; }
Get the kernel virtual address of a set of physical pages.
Get the kernel virtual address of a set of physical pages .
/*
	 * Allocate any KVA space that we need, this is done in a separate
	 * loop to prevent calling vmem_alloc while pinned.
	 */ /* Exit early if everything is covered by the DMAP */