/* XXXKSE All the code below only works in 1:1 needs changing */
ext = (struct pcb_ext *)kmem_alloc(kernel_map, ctob(IOPAGES+1));
if (ext == 0)
return (ENOMEM);
bzero(ext, sizeof(struct pcb_ext));
/* -16 is so we can convert a trapframe into vm86trapframe inplace */
ext->ext_tss.tss_esp0 = td->td_kstack + ctob(KSTACK_PAGES) -
sizeof(struct pcb) - 16;
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.
* We arbitrarily allocate 16 bytes here, to keep the starting
* address on a doubleword boundary.
*/
offset = PAGE_SIZE - 16;
ext->ext_tss.tss_ioopt =
(offset - ((unsigned)&ext->ext_tss - (unsigned)ext)) << 16;
ext->ext_iomap = (caddr_t)ext + offset;
ext->ext_vm86.vm86_intmap = (caddr_t)ext + offset - 32;
addr = (u_long *)ext->ext_vm86.vm86_intmap;
for (i = 0; i < (ctob(IOPAGES) + 32 + 16) / sizeof(u_long); i++)
*addr++ = ~0;
ssd.ssd_base = (unsigned)&ext->ext_tss;
ssd.ssd_limit -= ((unsigned)&ext->ext_tss - (unsigned)ext);
ssdtosd(&ssd, &ext->ext_tssd);
KASSERT(td->td_proc == curthread->td_proc, ("giving TSS to !curproc"));
KASSERT(td->td_pcb->pcb_ext == 0, ("already have a TSS!"));
mtx_lock_spin(&sched_lock);
td->td_pcb->pcb_ext = ext;
/* switch to the new TSS after syscall completes */
td->td_flags |= TDF_NEEDRESCHED;
mtx_unlock_spin(&sched_lock);
return 0;
}
static int
i386_set_ioperm(td, args)
struct thread *td;
char *args;
{
int i, error;