* dt_lock must be held. Returns with dt_lock held. */
| 447 | * dt_lock must be held. Returns with dt_lock held. |
| 448 | */ |
| 449 | struct proc_ldt * |
| 450 | user_ldt_alloc(struct mdproc *mdp, int len) |
| 451 | { |
| 452 | struct proc_ldt *pldt, *new_ldt; |
| 453 | |
| 454 | mtx_assert(&dt_lock, MA_OWNED); |
| 455 | mtx_unlock_spin(&dt_lock); |
| 456 | new_ldt = malloc(sizeof(struct proc_ldt), M_SUBPROC, M_WAITOK); |
| 457 | |
| 458 | new_ldt->ldt_len = len = NEW_MAX_LD(len); |
| 459 | new_ldt->ldt_base = pmap_trm_alloc(len * sizeof(union descriptor), |
| 460 | M_WAITOK | M_ZERO); |
| 461 | new_ldt->ldt_refcnt = 1; |
| 462 | new_ldt->ldt_active = 0; |
| 463 | |
| 464 | mtx_lock_spin(&dt_lock); |
| 465 | gdt_segs[GUSERLDT_SEL].ssd_base = (unsigned)new_ldt->ldt_base; |
| 466 | gdt_segs[GUSERLDT_SEL].ssd_limit = len * sizeof(union descriptor) - 1; |
| 467 | ssdtosd(&gdt_segs[GUSERLDT_SEL], &new_ldt->ldt_sd); |
| 468 | |
| 469 | if ((pldt = mdp->md_ldt) != NULL) { |
| 470 | if (len > pldt->ldt_len) |
| 471 | len = pldt->ldt_len; |
| 472 | bcopy(pldt->ldt_base, new_ldt->ldt_base, |
| 473 | len * sizeof(union descriptor)); |
| 474 | } else |
| 475 | bcopy(ldt, new_ldt->ldt_base, sizeof(union descriptor) * NLDT); |
| 476 | |
| 477 | return (new_ldt); |
| 478 | } |
| 479 | |
| 480 | /* |
| 481 | * Must be called with dt_lock held. Returns with dt_lock unheld. |
no test coverage detected