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!
_______________________________________________
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel