void up_initial_state(_TCB *tcb) { struct xcptcontext *xcp = &tcb->xcp; /* Initialize the initial exception register context structure */ memset(xcp, 0, sizeof(struct xcptcontext)); /* Save the initial stack pointer... the value of the stackpointer before * the "interrupt occurs." We don't know the value of REG_ESP yet.. * that depends on if a priority change is required or not. */ xcp->regs[REG_SP] = (uint32_t)tcb->adj_stack_ptr; /* Save the task entry point */ xcp->regs[REG_EIP] = (uint32_t)tcb->start; /* Set up the segment registers... assume the same segment as the caller. * That is not a good assumption in the long run. */ xcp->regs[REG_DS] = up_getds(); xcp->regs[REG_CS] = up_getcs(); xcp->regs[REG_SS] = up_getss(); /* Set supervisor- or user-mode, depending on how NuttX is configured and * what kind of thread is being started. Disable FIQs in any event * * If the kernel build is not selected, then all threads run in * supervisor-mode. */ #ifdef CONFIG_NUTTX_KERNEL # error "Missing logic for the CONFIG_NUTTX_KERNEL build" #endif /* Enable or disable interrupts, based on user configuration. If the IF * bit is set, maskable interrupts will be enabled. */ #ifndef CONFIG_SUPPRESS_INTERRUPTS xcp->regs[REG_EFLAGS] = X86_FLAGS_IF; #endif }
void up_savestate(uint32_t *regs) { uint8_t cpl; uint8_t rpl; /* First, just copy all of the registers */ up_copystate(regs, (uint32_t*)current_regs); /* The RES_SP and REG_SS values will not be saved by the interrupt handling * logic if there is no change in privilege level. In that case, we will * have to "fudge" those values here. For now, just overwrite the REG_SP * and REG_SS values with what we believe to be correct. Obviously, this * will have to change in the future to support multi-segment operation. * * Check for a change in privilege level. */ rpl = regs[REG_CS] & 3; cpl = up_getcs() & 3; DEBUGASSERT(rpl >= cpl); if (rpl == cpl) { /* No priority change, SP and SS are not present in the stack frame. * * The value saved in the REG_ESP will be the stackpointer value prior to * the execution of the PUSHA. It will point at REG_IRQNO. */ regs[REG_SP] = current_regs[REG_ESP] + 4*BOTTOM_NOPRIO; regs[REG_SS] = up_getss(); } else { DEBUGASSERT(regs[REG_SP] == current_regs[REG_ESP] + 4*BOTTOM_PRIO); } }