MCPcopy Create free account
hub / github.com/F-Stack/f-stack / pmap_map_io_transient

Function pmap_map_io_transient

freebsd/amd64/amd64/pmap.c:9964–10027  ·  view source on GitHub ↗

* 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

Source from the content-addressed store, hash-verified

9962 *
9963 */
9964boolean_t
9965pmap_map_io_transient(vm_page_t page[], vm_offset_t vaddr[], int count,
9966 boolean_t can_fault)
9967{
9968 vm_paddr_t paddr;
9969 boolean_t needs_mapping;
9970 pt_entry_t *pte;
9971 int cache_bits, error __unused, i;
9972
9973 /*
9974 * Allocate any KVA space that we need, this is done in a separate
9975 * loop to prevent calling vmem_alloc while pinned.
9976 */
9977 needs_mapping = FALSE;
9978 for (i = 0; i < count; i++) {
9979 paddr = VM_PAGE_TO_PHYS(page[i]);
9980 if (__predict_false(paddr >= dmaplimit)) {
9981 error = vmem_alloc(kernel_arena, PAGE_SIZE,
9982 M_BESTFIT | M_WAITOK, &vaddr[i]);
9983 KASSERT(error == 0, ("vmem_alloc failed: %d", error));
9984 needs_mapping = TRUE;
9985 } else {
9986 vaddr[i] = PHYS_TO_DMAP(paddr);
9987 }
9988 }
9989
9990 /* Exit early if everything is covered by the DMAP */
9991 if (!needs_mapping)
9992 return (FALSE);
9993
9994 /*
9995 * NB: The sequence of updating a page table followed by accesses
9996 * to the corresponding pages used in the !DMAP case is subject to
9997 * the situation described in the "AMD64 Architecture Programmer's
9998 * Manual Volume 2: System Programming" rev. 3.23, "7.3.1 Special
9999 * Coherency Considerations". Therefore, issuing the INVLPG right
10000 * after modifying the PTE bits is crucial.
10001 */
10002 if (!can_fault)
10003 sched_pin();
10004 for (i = 0; i < count; i++) {
10005 paddr = VM_PAGE_TO_PHYS(page[i]);
10006 if (paddr >= dmaplimit) {
10007 if (can_fault) {
10008 /*
10009 * Slow path, since we can get page faults
10010 * while mappings are active don't pin the
10011 * thread to the CPU and instead add a global
10012 * mapping visible to all CPUs.
10013 */
10014 pmap_qenter(vaddr[i], &page[i], 1);
10015 } else {
10016 pte = vtopte(vaddr[i]);
10017 cache_bits = pmap_cache_bits(kernel_pmap,
10018 page[i]->md.pat_mode, 0);
10019 pte_store(pte, paddr | X86_PG_RW | X86_PG_V |
10020 cache_bits);
10021 invlpg(vaddr[i]);

Callers 2

pmap_copy_pagesFunction · 0.70
uiomove_fromphysFunction · 0.70

Calls 6

vmem_allocFunction · 0.85
sched_pinFunction · 0.85
vtopteFunction · 0.85
pmap_qenterFunction · 0.70
pmap_cache_bitsFunction · 0.70
invlpgFunction · 0.50

Tested by

no test coverage detected