[PATCH 5/5] LEON3: use CPU_Fatal_halt for halt

Daniel Hellstrom daniel at gaisler.com
Fri Jul 4 09:54:53 UTC 2014


On 07/04/2014 08:25 AM, Sebastian Huber wrote:
> On 2014-07-03 09:29, Daniel Hellstrom wrote:
>> By removing the bsp_reset() mechanism and instead relying on the
>> CPU_Fatal_halt() routine SMP and single-core can halt by updating
>> the _Internal_errors_What_happened structure and set the state to
>> SYSTEM_STATE_TERMINATED (the generic way). This will be better
>> for test scripts and debugger that can generically look into why
>> the OS stopped.
>
> The reason for updating the system state and the _Internal_errors_What_happened structure after the fatal extensions is that this lowers the run-time environment requirements.  On uni-processor 
> systems you need only code memory, read-only data and a stack.  Access to global read-write data is not necessary for the initial fatal extensions.

This limitation is only during early boot right?

>
> The _CPU_Fatal_halt() is fine, I haven't done it this myself due to a lack of time.
>
>>
>> For SMP systems, only the fatal-reporting CPU waits until all other
>> CPUs are powered down (with a time out of one clock tick). The
>> reason why a fatal stop happend may be because CPU0 was soft-locked
>> up so we can never trust that CPU0 should do the halt for us.
>
> This is a very good change.
>
> [...]
>> +void bsp_fatal_extension(
>> +  rtems_fatal_source source,
>> +  bool is_internal,
>> +  rtems_fatal_code code
>> +)
>> +{
>> +  /* On SMP we must wait for all other CPUs not requesting a fatal halt, they
>> +   * are responding to another CPU's fatal request. These CPUs goes into
>> +   * power-down. The CPU requesting fatal halt waits for the others and then
>> +   * handles the system shutdown via the normal procedure.
>> +   */
>> +  #ifdef RTEMS_SMP
>> +  if ((source == RTEMS_FATAL_SOURCE_SMP) &&
>> +      (code == SMP_FATAL_SHUTDOWN_RESPONSE)) {
>> +    leon3_power_down_loop(); /* CPU didn't start shutdown sequence .. */
>> +  } else {
>> +    volatile struct irqmp_regs *irqmp = LEON3_IrqCtrl_Regs;
>> +
>> +    if (irqmp != NULL) {
>> +      /*
>> +       * Value was choosen to get something in the magnitude of 1ms on a 200MHz
>> +       * processor.
>> +       */
>> +      uint32_t max_wait = 1234567;
>> +      uint32_t self_cpu = rtems_get_current_processor();
>> +
>> +      uint32_t cpu_count = rtems_get_processor_count();
>> +      uint32_t halt_mask = 0;
>> +      uint32_t i;
>> +
>> +      for (i = 0; i < cpu_count; ++i) {
>> +        if (i != self_cpu) {
>> +          halt_mask |= UINT32_C(1) << i;
>> +        }
>> +      }
>
> The application my not run on all processors.  So you should add a check like this:
>
>   const Scheduler_Assignment *assignment = _Scheduler_Get_assignment( i );
>
>   if ( _Scheduler_Should_start_processor( assignment ) ) {
>     halt_mask |= UINT32_C(1) << i;
>   }

Interesting indeed, I was wondering how that could be done in RTEMS. Would it be okay if I sort this out in a separate patch? This code is just a move from bspreset.c.

Thanks for your comments!




More information about the devel mailing list