* Create a zbuf describing a range of user address space memory. Validate * page alignment, size requirements, etc. */
| 176 | * page alignment, size requirements, etc. |
| 177 | */ |
| 178 | static int |
| 179 | zbuf_setup(struct thread *td, vm_offset_t uaddr, size_t len, |
| 180 | struct zbuf **zbp) |
| 181 | { |
| 182 | struct zbuf *zb; |
| 183 | struct vm_map *map; |
| 184 | int error, i; |
| 185 | |
| 186 | *zbp = NULL; |
| 187 | |
| 188 | /* |
| 189 | * User address must be page-aligned. |
| 190 | */ |
| 191 | if (uaddr & PAGE_MASK) |
| 192 | return (EINVAL); |
| 193 | |
| 194 | /* |
| 195 | * Length must be an integer number of full pages. |
| 196 | */ |
| 197 | if (len & PAGE_MASK) |
| 198 | return (EINVAL); |
| 199 | |
| 200 | /* |
| 201 | * Length must not exceed per-buffer resource limit. |
| 202 | */ |
| 203 | if ((len / PAGE_SIZE) > BPF_MAX_PAGES) |
| 204 | return (EINVAL); |
| 205 | |
| 206 | /* |
| 207 | * Allocate the buffer and set up each page with is own sf_buf. |
| 208 | */ |
| 209 | error = 0; |
| 210 | zb = malloc(sizeof(*zb), M_BPF, M_ZERO | M_WAITOK); |
| 211 | zb->zb_uaddr = uaddr; |
| 212 | zb->zb_size = len; |
| 213 | zb->zb_numpages = len / PAGE_SIZE; |
| 214 | zb->zb_pages = malloc(sizeof(struct sf_buf *) * |
| 215 | zb->zb_numpages, M_BPF, M_ZERO | M_WAITOK); |
| 216 | map = &td->td_proc->p_vmspace->vm_map; |
| 217 | for (i = 0; i < zb->zb_numpages; i++) { |
| 218 | zb->zb_pages[i] = zbuf_sfbuf_get(map, |
| 219 | uaddr + (i * PAGE_SIZE)); |
| 220 | if (zb->zb_pages[i] == NULL) { |
| 221 | error = EFAULT; |
| 222 | goto error; |
| 223 | } |
| 224 | } |
| 225 | zb->zb_header = |
| 226 | (struct bpf_zbuf_header *)sf_buf_kva(zb->zb_pages[0]); |
| 227 | bzero(zb->zb_header, sizeof(*zb->zb_header)); |
| 228 | *zbp = zb; |
| 229 | return (0); |
| 230 | |
| 231 | error: |
| 232 | zbuf_free(zb); |
| 233 | return (error); |
| 234 | } |
| 235 |
no test coverage detected