* Implement uiomove(9) from physical memory using a combination * of the direct mapping and sf_bufs to reduce the creation and * destruction of ephemeral mappings. */
| 61 | * destruction of ephemeral mappings. |
| 62 | */ |
| 63 | int |
| 64 | uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio) |
| 65 | { |
| 66 | struct sf_buf *sf; |
| 67 | struct thread *td = curthread; |
| 68 | struct iovec *iov; |
| 69 | void *cp; |
| 70 | vm_offset_t page_offset; |
| 71 | vm_paddr_t pa; |
| 72 | vm_page_t m; |
| 73 | size_t cnt; |
| 74 | int error = 0; |
| 75 | int save = 0; |
| 76 | |
| 77 | KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, |
| 78 | ("uiomove_fromphys: mode")); |
| 79 | KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, |
| 80 | ("uiomove_fromphys proc")); |
| 81 | save = td->td_pflags & TDP_DEADLKTREAT; |
| 82 | td->td_pflags |= TDP_DEADLKTREAT; |
| 83 | while (n > 0 && uio->uio_resid) { |
| 84 | iov = uio->uio_iov; |
| 85 | cnt = iov->iov_len; |
| 86 | if (cnt == 0) { |
| 87 | uio->uio_iov++; |
| 88 | uio->uio_iovcnt--; |
| 89 | continue; |
| 90 | } |
| 91 | if (cnt > n) |
| 92 | cnt = n; |
| 93 | page_offset = offset & PAGE_MASK; |
| 94 | cnt = ulmin(cnt, PAGE_SIZE - page_offset); |
| 95 | m = ma[offset >> PAGE_SHIFT]; |
| 96 | pa = VM_PAGE_TO_PHYS(m); |
| 97 | if (MIPS_DIRECT_MAPPABLE(pa)) { |
| 98 | sf = NULL; |
| 99 | cp = (char *)MIPS_PHYS_TO_DIRECT(pa) + page_offset; |
| 100 | /* |
| 101 | * flush all mappings to this page, KSEG0 address first |
| 102 | * in order to get it overwritten by correct data |
| 103 | */ |
| 104 | mips_dcache_wbinv_range((vm_offset_t)cp, cnt); |
| 105 | pmap_flush_pvcache(m); |
| 106 | } else { |
| 107 | sf = sf_buf_alloc(m, 0); |
| 108 | cp = (char *)sf_buf_kva(sf) + page_offset; |
| 109 | } |
| 110 | switch (uio->uio_segflg) { |
| 111 | case UIO_USERSPACE: |
| 112 | maybe_yield(); |
| 113 | if (uio->uio_rw == UIO_READ) |
| 114 | error = copyout(cp, iov->iov_base, cnt); |
| 115 | else |
| 116 | error = copyin(iov->iov_base, cp, cnt); |
| 117 | if (error) { |
| 118 | if (sf != NULL) |
| 119 | sf_buf_free(sf); |
| 120 | goto out; |
no test coverage detected