* Map a set of physical memory pages into the kernel virtual * address space. Return a pointer to where it is mapped. This * routine is intended to be used for mapping device memory, * NOT real memory. */
| 8917 | * NOT real memory. |
| 8918 | */ |
| 8919 | static void * |
| 8920 | pmap_mapdev_internal(vm_paddr_t pa, vm_size_t size, int mode, int flags) |
| 8921 | { |
| 8922 | struct pmap_preinit_mapping *ppim; |
| 8923 | vm_offset_t va, offset; |
| 8924 | vm_size_t tmpsize; |
| 8925 | int i; |
| 8926 | |
| 8927 | offset = pa & PAGE_MASK; |
| 8928 | size = round_page(offset + size); |
| 8929 | pa = trunc_page(pa); |
| 8930 | |
| 8931 | if (!pmap_initialized) { |
| 8932 | va = 0; |
| 8933 | for (i = 0; i < PMAP_PREINIT_MAPPING_COUNT; i++) { |
| 8934 | ppim = pmap_preinit_mapping + i; |
| 8935 | if (ppim->va == 0) { |
| 8936 | ppim->pa = pa; |
| 8937 | ppim->sz = size; |
| 8938 | ppim->mode = mode; |
| 8939 | ppim->va = virtual_avail; |
| 8940 | virtual_avail += size; |
| 8941 | va = ppim->va; |
| 8942 | break; |
| 8943 | } |
| 8944 | } |
| 8945 | if (va == 0) |
| 8946 | panic("%s: too many preinit mappings", __func__); |
| 8947 | } else { |
| 8948 | /* |
| 8949 | * If we have a preinit mapping, re-use it. |
| 8950 | */ |
| 8951 | for (i = 0; i < PMAP_PREINIT_MAPPING_COUNT; i++) { |
| 8952 | ppim = pmap_preinit_mapping + i; |
| 8953 | if (ppim->pa == pa && ppim->sz == size && |
| 8954 | (ppim->mode == mode || |
| 8955 | (flags & MAPDEV_SETATTR) == 0)) |
| 8956 | return ((void *)(ppim->va + offset)); |
| 8957 | } |
| 8958 | /* |
| 8959 | * If the specified range of physical addresses fits within |
| 8960 | * the direct map window, use the direct map. |
| 8961 | */ |
| 8962 | if (pa < dmaplimit && pa + size <= dmaplimit) { |
| 8963 | va = PHYS_TO_DMAP(pa); |
| 8964 | if ((flags & MAPDEV_SETATTR) != 0) { |
| 8965 | PMAP_LOCK(kernel_pmap); |
| 8966 | i = pmap_change_props_locked(va, size, |
| 8967 | PROT_NONE, mode, flags); |
| 8968 | PMAP_UNLOCK(kernel_pmap); |
| 8969 | } else |
| 8970 | i = 0; |
| 8971 | if (!i) |
| 8972 | return ((void *)(va + offset)); |
| 8973 | } |
| 8974 | va = kva_alloc(size); |
| 8975 | if (va == 0) |
| 8976 | panic("%s: Couldn't allocate KVA", __func__); |
no test coverage detected