Changeset View
Changeset View
Standalone View
Standalone View
sys/i386/i386/sys_machdep.c
Show First 20 Lines • Show All 288 Lines • ▼ Show 20 Lines | struct soft_segment_descriptor ssd = { | ||||
SDT_SYS386TSS, /* segment type */ | SDT_SYS386TSS, /* segment type */ | ||||
0, /* priority level */ | 0, /* priority level */ | ||||
1, /* descriptor present */ | 1, /* descriptor present */ | ||||
0, 0, | 0, 0, | ||||
0, /* default 32 size */ | 0, /* default 32 size */ | ||||
0 /* granularity */ | 0 /* granularity */ | ||||
}; | }; | ||||
ext = (struct pcb_ext *)kmem_malloc(kernel_arena, ctob(IOPAGES+1), | ext = pmap_trm_alloc(ctob(IOPAGES + 1), M_WAITOK | M_ZERO); | ||||
M_WAITOK | M_ZERO); | |||||
/* -16 is so we can convert a trapframe into vm86trapframe inplace */ | /* -16 is so we can convert a trapframe into vm86trapframe inplace */ | ||||
ext->ext_tss.tss_esp0 = (vm_offset_t)td->td_pcb - 16; | |||||
ext->ext_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL); | ext->ext_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL); | ||||
/* | /* | ||||
* The last byte of the i/o map must be followed by an 0xff byte. | * The last byte of the i/o map must be followed by an 0xff byte. | ||||
* We arbitrarily allocate 16 bytes here, to keep the starting | * We arbitrarily allocate 16 bytes here, to keep the starting | ||||
* address on a doubleword boundary. | * address on a doubleword boundary. | ||||
*/ | */ | ||||
offset = PAGE_SIZE - 16; | offset = PAGE_SIZE - 16; | ||||
ext->ext_tss.tss_ioopt = | ext->ext_tss.tss_ioopt = | ||||
Show All 9 Lines | i386_extend_pcb(struct thread *td) | ||||
ssd.ssd_limit -= ((unsigned)&ext->ext_tss - (unsigned)ext); | ssd.ssd_limit -= ((unsigned)&ext->ext_tss - (unsigned)ext); | ||||
ssdtosd(&ssd, &ext->ext_tssd); | ssdtosd(&ssd, &ext->ext_tssd); | ||||
KASSERT(td == curthread, ("giving TSS to !curthread")); | KASSERT(td == curthread, ("giving TSS to !curthread")); | ||||
KASSERT(td->td_pcb->pcb_ext == 0, ("already have a TSS!")); | KASSERT(td->td_pcb->pcb_ext == 0, ("already have a TSS!")); | ||||
/* Switch to the new TSS. */ | /* Switch to the new TSS. */ | ||||
critical_enter(); | critical_enter(); | ||||
ext->ext_tss.tss_esp0 = PCPU_GET(trampstk); | |||||
td->td_pcb->pcb_ext = ext; | td->td_pcb->pcb_ext = ext; | ||||
PCPU_SET(private_tss, 1); | PCPU_SET(private_tss, 1); | ||||
*PCPU_GET(tss_gdt) = ext->ext_tssd; | *PCPU_GET(tss_gdt) = ext->ext_tssd; | ||||
ltr(GSEL(GPROC0_SEL, SEL_KPL)); | ltr(GSEL(GPROC0_SEL, SEL_KPL)); | ||||
critical_exit(); | critical_exit(); | ||||
return 0; | return 0; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 118 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
struct proc_ldt *pldt, *new_ldt; | struct proc_ldt *pldt, *new_ldt; | ||||
mtx_assert(&dt_lock, MA_OWNED); | mtx_assert(&dt_lock, MA_OWNED); | ||||
mtx_unlock_spin(&dt_lock); | mtx_unlock_spin(&dt_lock); | ||||
new_ldt = malloc(sizeof(struct proc_ldt), M_SUBPROC, M_WAITOK); | new_ldt = malloc(sizeof(struct proc_ldt), M_SUBPROC, M_WAITOK); | ||||
new_ldt->ldt_len = len = NEW_MAX_LD(len); | new_ldt->ldt_len = len = NEW_MAX_LD(len); | ||||
new_ldt->ldt_base = (caddr_t)kmem_malloc(kernel_arena, | new_ldt->ldt_base = pmap_trm_alloc(len * sizeof(union descriptor), | ||||
len * sizeof(union descriptor), M_WAITOK | M_ZERO); | M_WAITOK | M_ZERO); | ||||
new_ldt->ldt_refcnt = 1; | new_ldt->ldt_refcnt = 1; | ||||
new_ldt->ldt_active = 0; | new_ldt->ldt_active = 0; | ||||
mtx_lock_spin(&dt_lock); | mtx_lock_spin(&dt_lock); | ||||
gdt_segs[GUSERLDT_SEL].ssd_base = (unsigned)new_ldt->ldt_base; | gdt_segs[GUSERLDT_SEL].ssd_base = (unsigned)new_ldt->ldt_base; | ||||
gdt_segs[GUSERLDT_SEL].ssd_limit = len * sizeof(union descriptor) - 1; | gdt_segs[GUSERLDT_SEL].ssd_limit = len * sizeof(union descriptor) - 1; | ||||
ssdtosd(&gdt_segs[GUSERLDT_SEL], &new_ldt->ldt_sd); | ssdtosd(&gdt_segs[GUSERLDT_SEL], &new_ldt->ldt_sd); | ||||
if ((pldt = mdp->md_ldt) != NULL) { | if ((pldt = mdp->md_ldt) != NULL) { | ||||
if (len > pldt->ldt_len) | if (len > pldt->ldt_len) | ||||
len = pldt->ldt_len; | len = pldt->ldt_len; | ||||
bcopy(pldt->ldt_base, new_ldt->ldt_base, | bcopy(pldt->ldt_base, new_ldt->ldt_base, | ||||
len * sizeof(union descriptor)); | len * sizeof(union descriptor)); | ||||
} else | } else | ||||
bcopy(ldt, new_ldt->ldt_base, sizeof(ldt)); | bcopy(ldt, new_ldt->ldt_base, sizeof(union descriptor) * NLDT); | ||||
return (new_ldt); | return (new_ldt); | ||||
} | } | ||||
/* | /* | ||||
* Must be called with dt_lock held. Returns with dt_lock unheld. | * Must be called with dt_lock held. Returns with dt_lock unheld. | ||||
*/ | */ | ||||
void | void | ||||
Show All 20 Lines | |||||
void | void | ||||
user_ldt_deref(struct proc_ldt *pldt) | user_ldt_deref(struct proc_ldt *pldt) | ||||
{ | { | ||||
mtx_assert(&dt_lock, MA_OWNED); | mtx_assert(&dt_lock, MA_OWNED); | ||||
if (--pldt->ldt_refcnt == 0) { | if (--pldt->ldt_refcnt == 0) { | ||||
mtx_unlock_spin(&dt_lock); | mtx_unlock_spin(&dt_lock); | ||||
kmem_free(kernel_arena, (vm_offset_t)pldt->ldt_base, | pmap_trm_free(pldt->ldt_base, pldt->ldt_len * | ||||
pldt->ldt_len * sizeof(union descriptor)); | sizeof(union descriptor)); | ||||
free(pldt, M_SUBPROC); | free(pldt, M_SUBPROC); | ||||
} else | } else | ||||
mtx_unlock_spin(&dt_lock); | mtx_unlock_spin(&dt_lock); | ||||
} | } | ||||
/* | /* | ||||
* Note for the authors of compat layers (linux, etc): copyout() in | * Note for the authors of compat layers (linux, etc): copyout() in | ||||
* the function below is not a problem since it presents data in | * the function below is not a problem since it presents data in | ||||
▲ Show 20 Lines • Show All 239 Lines • ▼ Show 20 Lines | if ((pldt = mdp->md_ldt) == NULL || len > pldt->ldt_len) { | ||||
if (pldt != NULL) { | if (pldt != NULL) { | ||||
if (new_ldt->ldt_len <= pldt->ldt_len) { | if (new_ldt->ldt_len <= pldt->ldt_len) { | ||||
/* | /* | ||||
* We just lost the race for allocation, so | * We just lost the race for allocation, so | ||||
* free the new object and return. | * free the new object and return. | ||||
*/ | */ | ||||
mtx_unlock_spin(&dt_lock); | mtx_unlock_spin(&dt_lock); | ||||
kmem_free(kernel_arena, | pmap_trm_free(new_ldt->ldt_base, | ||||
(vm_offset_t)new_ldt->ldt_base, | |||||
new_ldt->ldt_len * sizeof(union descriptor)); | new_ldt->ldt_len * sizeof(union descriptor)); | ||||
free(new_ldt, M_SUBPROC); | free(new_ldt, M_SUBPROC); | ||||
mtx_lock_spin(&dt_lock); | mtx_lock_spin(&dt_lock); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* We have to substitute the current LDT entry for | * We have to substitute the current LDT entry for | ||||
Show All 16 Lines | #ifdef SMP | ||||
mtx_unlock_spin(&dt_lock); | mtx_unlock_spin(&dt_lock); | ||||
smp_rendezvous(NULL, set_user_ldt_rv, NULL, | smp_rendezvous(NULL, set_user_ldt_rv, NULL, | ||||
td->td_proc->p_vmspace); | td->td_proc->p_vmspace); | ||||
#else | #else | ||||
set_user_ldt_locked(&td->td_proc->p_md); | set_user_ldt_locked(&td->td_proc->p_md); | ||||
mtx_unlock_spin(&dt_lock); | mtx_unlock_spin(&dt_lock); | ||||
#endif | #endif | ||||
if (old_ldt_base != NULL_LDT_BASE) { | if (old_ldt_base != NULL_LDT_BASE) { | ||||
kmem_free(kernel_arena, (vm_offset_t)old_ldt_base, | pmap_trm_free(old_ldt_base, old_ldt_len * | ||||
old_ldt_len * sizeof(union descriptor)); | sizeof(union descriptor)); | ||||
free(new_ldt, M_SUBPROC); | free(new_ldt, M_SUBPROC); | ||||
} | } | ||||
mtx_lock_spin(&dt_lock); | mtx_lock_spin(&dt_lock); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } |