[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Dynamic switching of co-processor context



I think this is a nice idea but there may be users who prefer
the simpler and more deterministic approach of just always
switching the co-processor context.

If we go with dynamic switching then there could be a slightly
different strategy which might (I haven't thought of this deeply)
eliminate all the issues with keeping MSR state consistent.

a) Keep existing lazy-context switching code. If -- at context-switch
     time -- the saved MSR indicates that the 'heir' task needs the
    coprocessor then change ownership.

b) If a task incurs an exception because it tries to use the co-processor
    but it is disabled then let the exception handler change ownership
    and enable the co-processor for the task.

Note that the co-processor-enable bit is never changed for a non-executing
task.

This strategy seems reasonable under the assumption that a task
who uses the co-processor once is likely to use it in the future again.
For tasks that 'always' use the co-processor it eliminates the need
for handling an exception every time the task is given the CPU.

-- Till


Sebastian Huber wrote:
> Hi!
>
> This discussion focus on the PowerPC, but other architectures may be similar.
>
> Suppose you have a co-processor (floating-point, digital signal processing,
> vector unit) which only few tasks need (more than one) or that is seldom used
> by tasks (printf() for example), then it is desirable to remove the
> co-processor context switching from the normal context switch.  The separation
> of the context switching results in a reduced context switch time.  This
> reduces also the worst case time of disabled interrupts (= worst case interrupt
> latency WCIL).  On the PowerPC the WCIL is very likely this sequence:
>
>   1. An interrupt handler finishes its work
>   2. External exceptions are disabled at the end of interrupt processing
>   3. First half of the exception epilogue
>   4. A context switch is necessary
>   5. Context switch to a task that was suspended by an interrupt
>   6. Second half of the exception epilogue
>   7. Return from exception
>   8. External exceptions are enabled again
>
> In total we have "maximum context switch time" + "exception epilogue time" = WCIL.
> The co-processor context switching will be done in a task context and thus does
> not affect higher priority tasks.
>
> It will be assumed that you can enable or disable the co-processor availability
> in a machine state register.  At most one task may be the owner of the
> co-processor context.  If another task needs the co-processor the ownership has
> to change.  This requires saving of the context for the previous owner and
> restoring of the context for the new owner.  The tasks not owning the
> co-processor trigger an exception if they use a co-processor facility.  The
> exception handler hands over the ownership.  This leads to the problem that the
> machine state of a not executing task has to be modified.  Typically the
> sequence to modify the machine state is
>
>   1. Move the machine state register into a general purpose register.
>   2. Modify the value in the general purpose register.
>   3. Write the modfied value back into the machine state register.
>
> Here we have the problem that this sequence may be interrupted at any time.  If
> a context switch happens during 2. and 3. and the co-processor ownership
> changes in the meantime, then the task overwrites the updated machine state
> directly after it resumes execution and this may leads to a corrupted
> co-processor context.  On the PowerPC such a sequence is used to disable the
> interrupts, so we need a workaround.
>
> Variant 1:
>   Use a special instruction to disable interrupts atomically.  Not
>   every variant may have this.
>
> Variant 2:
>   Disable the co-processor availability in every modified machine
>   state register value.  Example:
>
>     msr = read_from_msr()
>     modify(msr)
>     disable_co_processor(msr)
>     write_to_msr(msr)
>     synchronize()
>
>   The PowerPC needs a synchronization instruction after the move to MSR if
>   the FP bit is switched off.
>
>   This variant is easy.  The drawback is that the co-processor may be
>   switched off more often than it is needed.
>
> Variant 3:
>   Check the co-processor ownership after the machine state register
>   update and disable the co-processor availability if required.  Example:
>
>   executing = _Thread_Executing
>   msr = read_from_msr()
>   modify(msr)
>   write_to_msr(msr)
>   if co_processor_owner != executing
>     disable_co_processor(msr)
>     write_to_msr(msr)
>     synchronize()
>
> Each variant will result in a modified interrupt enable, flash, and disable
> code in the Cpukit.  The user has to review its code for usages of the machine
> state register.  The question is how to deal with this?  We also need an
> exception handler.  Currently on the PowerPC exception handlers are not
> available in the Cpukit.  I converted most of the BSPs to use the shared
> exception code (only mpc5xx is missing) and will commit this in the near
> future.  So it is feasible that we have the PowerPC exception code back in the
> Cpukit some time.
>
> I would be glad if you send me some comments to this.
>
>