| 4520 | "Specifies the number of guard pages for a stack that grows"); |
| 4521 | |
| 4522 | static int |
| 4523 | vm_map_stack_locked(vm_map_t map, vm_offset_t addrbos, vm_size_t max_ssize, |
| 4524 | vm_size_t growsize, vm_prot_t prot, vm_prot_t max, int cow) |
| 4525 | { |
| 4526 | vm_map_entry_t new_entry, prev_entry; |
| 4527 | vm_offset_t bot, gap_bot, gap_top, top; |
| 4528 | vm_size_t init_ssize, sgp; |
| 4529 | int orient, rv; |
| 4530 | |
| 4531 | /* |
| 4532 | * The stack orientation is piggybacked with the cow argument. |
| 4533 | * Extract it into orient and mask the cow argument so that we |
| 4534 | * don't pass it around further. |
| 4535 | */ |
| 4536 | orient = cow & (MAP_STACK_GROWS_DOWN | MAP_STACK_GROWS_UP); |
| 4537 | KASSERT(orient != 0, ("No stack grow direction")); |
| 4538 | KASSERT(orient != (MAP_STACK_GROWS_DOWN | MAP_STACK_GROWS_UP), |
| 4539 | ("bi-dir stack")); |
| 4540 | |
| 4541 | if (max_ssize == 0 || |
| 4542 | !vm_map_range_valid(map, addrbos, addrbos + max_ssize)) |
| 4543 | return (KERN_INVALID_ADDRESS); |
| 4544 | sgp = ((curproc->p_flag2 & P2_STKGAP_DISABLE) != 0 || |
| 4545 | (curproc->p_fctl0 & NT_FREEBSD_FCTL_STKGAP_DISABLE) != 0) ? 0 : |
| 4546 | (vm_size_t)stack_guard_page * PAGE_SIZE; |
| 4547 | if (sgp >= max_ssize) |
| 4548 | return (KERN_INVALID_ARGUMENT); |
| 4549 | |
| 4550 | init_ssize = growsize; |
| 4551 | if (max_ssize < init_ssize + sgp) |
| 4552 | init_ssize = max_ssize - sgp; |
| 4553 | |
| 4554 | /* If addr is already mapped, no go */ |
| 4555 | if (vm_map_lookup_entry(map, addrbos, &prev_entry)) |
| 4556 | return (KERN_NO_SPACE); |
| 4557 | |
| 4558 | /* |
| 4559 | * If we can't accommodate max_ssize in the current mapping, no go. |
| 4560 | */ |
| 4561 | if (vm_map_entry_succ(prev_entry)->start < addrbos + max_ssize) |
| 4562 | return (KERN_NO_SPACE); |
| 4563 | |
| 4564 | /* |
| 4565 | * We initially map a stack of only init_ssize. We will grow as |
| 4566 | * needed later. Depending on the orientation of the stack (i.e. |
| 4567 | * the grow direction) we either map at the top of the range, the |
| 4568 | * bottom of the range or in the middle. |
| 4569 | * |
| 4570 | * Note: we would normally expect prot and max to be VM_PROT_ALL, |
| 4571 | * and cow to be 0. Possibly we should eliminate these as input |
| 4572 | * parameters, and just pass these values here in the insert call. |
| 4573 | */ |
| 4574 | if (orient == MAP_STACK_GROWS_DOWN) { |
| 4575 | bot = addrbos + max_ssize - init_ssize; |
| 4576 | top = bot + init_ssize; |
| 4577 | gap_bot = addrbos; |
| 4578 | gap_top = bot; |
| 4579 | } else /* if (orient == MAP_STACK_GROWS_UP) */ { |
no test coverage detected