Beispiel #1
0
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);
    }
}