[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