* Used to map a range of physical addresses into kernel * virtual address space. * * The value passed in '*virt' is a suggested virtual address for * the mapping. Architectures which can support a direct-mapped * physical to virtual region can return the appropriate address * within that region, leaving '*virt' unchanged. Other * architectures should map the pages starting at '*virt'
| 1389 | * the function is used herein! |
| 1390 | */ |
| 1391 | vm_offset_t |
| 1392 | pmap_map(vm_offset_t *virt, vm_paddr_t start, vm_paddr_t end, int prot) |
| 1393 | { |
| 1394 | vm_offset_t va, sva; |
| 1395 | vm_paddr_t pte1_offset; |
| 1396 | pt1_entry_t npte1; |
| 1397 | uint32_t l1prot, l2prot; |
| 1398 | uint32_t l1attr, l2attr; |
| 1399 | |
| 1400 | PDEBUG(1, printf("%s: virt = %#x, start = %#x, end = %#x (size = %#x)," |
| 1401 | " prot = %d\n", __func__, *virt, start, end, end - start, prot)); |
| 1402 | |
| 1403 | l2prot = (prot & VM_PROT_WRITE) ? PTE2_AP_KRW : PTE2_AP_KR; |
| 1404 | l2prot |= (prot & VM_PROT_EXECUTE) ? PTE2_X : PTE2_NX; |
| 1405 | l1prot = ATTR_TO_L1(l2prot); |
| 1406 | |
| 1407 | l2attr = PTE2_ATTR_DEFAULT; |
| 1408 | l1attr = ATTR_TO_L1(l2attr); |
| 1409 | |
| 1410 | va = *virt; |
| 1411 | /* |
| 1412 | * Does the physical address range's size and alignment permit at |
| 1413 | * least one section mapping to be created? |
| 1414 | */ |
| 1415 | pte1_offset = start & PTE1_OFFSET; |
| 1416 | if ((end - start) - ((PTE1_SIZE - pte1_offset) & PTE1_OFFSET) >= |
| 1417 | PTE1_SIZE) { |
| 1418 | /* |
| 1419 | * Increase the starting virtual address so that its alignment |
| 1420 | * does not preclude the use of section mappings. |
| 1421 | */ |
| 1422 | if ((va & PTE1_OFFSET) < pte1_offset) |
| 1423 | va = pte1_trunc(va) + pte1_offset; |
| 1424 | else if ((va & PTE1_OFFSET) > pte1_offset) |
| 1425 | va = pte1_roundup(va) + pte1_offset; |
| 1426 | } |
| 1427 | sva = va; |
| 1428 | while (start < end) { |
| 1429 | if ((start & PTE1_OFFSET) == 0 && end - start >= PTE1_SIZE) { |
| 1430 | KASSERT((va & PTE1_OFFSET) == 0, |
| 1431 | ("%s: misaligned va %#x", __func__, va)); |
| 1432 | npte1 = PTE1_KERN(start, l1prot, l1attr); |
| 1433 | pmap_kenter_pte1(va, npte1); |
| 1434 | va += PTE1_SIZE; |
| 1435 | start += PTE1_SIZE; |
| 1436 | } else { |
| 1437 | pmap_kenter_prot_attr(va, start, l2prot, l2attr); |
| 1438 | va += PAGE_SIZE; |
| 1439 | start += PAGE_SIZE; |
| 1440 | } |
| 1441 | } |
| 1442 | tlb_flush_range(sva, va - sva); |
| 1443 | *virt = va; |
| 1444 | return (sva); |
| 1445 | } |
| 1446 | |
| 1447 | /* |
| 1448 | * Make a temporary mapping for a physical address. |
nothing calls this directly
no test coverage detected