/* * Functions for entering user mode. * * This should not be used by threads returning from traps - they * should just return from mips_trap(). It should be used by threads * entering user mode for the first time - whether the child thread in * a fork(), or into a brand-new address space after exec(), or when * starting the first userlevel program. * * mips_usermode is the common code. It should not be called outside * the mips port. * * md_usermode is meant for use in exec and equivalent. * md_forkentry, in syscall.c, is meant for use in fork. */ void mips_usermode(struct trapframe *tf) { /* * Interrupts should be off within the kernel while entering * usermode. However, while in usermode, interrupts should be * on. To interact properly with the spl-handling logic above, * we call splhigh() to disable interrupts, but set curspl * explicitly to 0. */ splhigh(); curspl = 0; /* * This assertion will fail if either * (1) curkstack is corrupted, or * (2) the trap frame is not on our own kernel stack. * * If curkstack is corrupted, the next trap back to the kernel * will (most likely) hang the system, so it's better to find * out now. * * It's necessary for the trap frame used here to be on the * current thread's own stack. It cannot correctly be on either * another thread's stack or in the kernel heap. (Why?) */ assert(SAME_STACK(curkstack-1, (vaddr_t)tf)); /* * This actually does it. See exception.S. */ asm_usermode(tf); }
/* * Functions for entering user mode. * * This should not be used by threads returning from traps - they * should just return from mips_trap(). It should be used by threads * entering user mode for the first time - whether the child thread in * a fork(), or into a brand-new address space after exec(), or when * starting the first userlevel program. * * mips_usermode is the common code. It should not be called outside * the mips port. * * md_usermode is meant for use in exec and equivalent. * md_forkentry, in syscall.c, is meant for use in fork. */ void mips_usermode(struct trapframe *tf) { /* * Interrupts should be off within the kernel while entering * usermode. However, while in usermode, interrupts should be * on. To interact properly with the spl-handling logic above, * we call splhigh() to disable interrupts, but set curspl * explicitly to 0. */ splhigh(); curspl = 0; /* * If curkstack is wrong, chances are the first trap back to * the kernel will hang the system. So make sure it's something * near correct. * * This test assumes that tf is on our own thread stack, but * that's more or less necessary anyway. */ assert(((curkstack-1) & 0xffffe000)==(((u_int32_t)tf) & 0xffffe000)); /* * This actually does it. See exception.S. */ asm_usermode(tf); }
/* * Function for entering user mode. * * This should not be used by threads returning from traps - they * should just return from mips_trap(). It should be used by threads * entering user mode for the first time - whether the child thread in * a fork(), or into a brand-new address space after exec(), or when * starting the first userlevel program. * * It works by jumping into the exception return code. * * mips_usermode is common code for this. It cannot usefully be called * outside the mips port, but should be called from one of the * following places: * - enter_new_process, for use by exec and equivalent. * - enter_forked_process, in syscall.c, for use by fork. */ void mips_usermode(struct trapframe *tf) { /* * Interrupts should be off within the kernel while entering * user mode. However, while in user mode, interrupts should * be on. To interact properly with the spl-handling logic * above, we explicitly call spl0() and then call cpu_irqoff(). */ spl0(); cpu_irqoff(); cputhreads[curcpu->c_number] = (vaddr_t)curthread; cpustacks[curcpu->c_number] = (vaddr_t)curthread->t_stack + STACK_SIZE; /* * This assertion will fail if either * (1) cpustacks[] is corrupted, or * (2) the trap frame is not on our own kernel stack, or * (3) the boot thread tries to enter user mode. * * If cpustacks[] is corrupted, the next trap back to the * kernel will (most likely) hang the system, so it's better * to find out now. * * It's necessary for the trap frame used here to be on the * current thread's own stack. It cannot correctly be on * either another thread's stack or in the kernel heap. * (Exercise: why?) */ KASSERT(((vaddr_t)tf) >= ((vaddr_t)curthread->t_stack)); KASSERT(((vaddr_t)tf) < ((vaddr_t)curthread->t_stack+STACK_SIZE)); //KASSERT(SAME_STACK(cpustacks[curcpu->c_number]-1, (vaddr_t)tf)); /* * This actually does it. See exception.S. */ asm_usermode(tf); }