Re: [PATCH v1 3/5] cpukit/aarch64: Add Exception Manager support

2021-09-08 Thread Chris Johns


On 2/9/21 3:36 am, Kinsey Moore wrote:
> On 9/1/2021 10:58, Sebastian Huber wrote:
>> On 01/09/2021 17:48, Sebastian Huber wrote:
>>> So, my proposal would be something like this:
>>>
>>> 1. Processor jumps to exception prologue
>>>
>>> 2. Exception prologue saves the context to CPU exception frame
>>>
>>> 3. Exception prologue calls rtems_fatal() which does not return
>>>
>>> For the signal mapping you provide a fatal extension:
>>>
>>> 1. If the source is not RTEMS_FATAL_SOURCE_EXCEPTION, then return (system
>>> terminates).
>>>
>>> 2. If the exception type cannot be handled, then return (system terminates).
>>>
>>> 3. Add a post-switch action to the executing thread.
>>>
>>> 4. Call _CPU_Exception_return( frame )
>>>
>>> The  _CPU_Exception_return( frame ) should:
>>>
>>> 1. Save the CPU exception return information to the stack of the executing
>>> thread.
>>>
>>> 2. Switch to the stack of the executing thread and to thread context with
>>> interrupts disabled.
>>>
>>> 3. Do something similar to the interrupt return.
>>>
>>> 4. The thread dispatch will call the post-switch extension which could raise
>>> a signal.
>>>
>>> This approach avoids a new user extension and it avoids a potentially dead
>>> code in the exception epilogue.
>>
>> Chris, I guess you have something like this
>>
>> _CPU_Exception_return( frame )
>>
>> in libdebugger currently?
>>
> I expected that since libdebugger wasn't built on the fatal error extension
> mechanism that it wasn't suitable for that type of functionality.
> 
> One thing I've been trying to avoid with the current approach is manual
> unwinding of the exception stack and the side-effects of other fatal error
> extensions. I suppose I could orchestrate the ordering of existing extensions
> such that recoverable exception handlers run before anything else.
> 

[ sorry, just catching up ]

The most difficult back end for libdebugger is ARM. The vectors are caught here:

https://git.rtems.org/rtems/tree/cpukit/libdebugger/rtems-debugger-arm.c#n1712

at the cp15 level so they are naked. In the current code the stack frame needs
to be left untouched. The exception is handled in C with:

static void __attribute__((naked))
target_exception_supervisor_call(void)
{
  CPU_Exception_frame* frame;
  ARM_SWITCH_REG;
  /*
   * The PC offset needs to be reviewed so we move past a svc
   * instruction. This can then be used as a user breakpoint. The issue is
   * this exception is used by the BKPT instruction in the prefetch abort
   * handler to signal a TRAP.
   */
  EXCEPTION_ENTRY_EXC();
  arm_debug_break_unload();
  arm_debug_enable_interrupts();
  EXCEPTION_ENTRY_THREAD(frame);
  frame->vector = 2;
  target_exception(frame);
  EXCEPTION_EXIT_THREAD(frame);
  arm_debug_commit_interrupt_disable();
  arm_debug_break_load();
  EXCEPTION_EXIT_EXC();
}

The macros EXCEPTION_ENTRY_THREAD and EXCEPTION_EXIT_THREAD is the difficult asm
code where the exception stack frame is copied from the exception stack to the
executing thread's stack and back again. This is important because the model is
now per thread so once the executing thread is suspended other threads can run
and other exceptions can occur.

The call `target_exception(frame);` is on the thread's stack and CPU context so
all normal thread calls can happen including blocking.

I suppose you could move the EXCEPTION_ENTRY_EXC processing down a level or so
but the asm code handling this would need to adjust to the different stack
layout and I am not sure how this gets effected by -O levels. The hard part of
moving to _CPU_Exception_return( frame ) is how you recreate the return path
exception stack's frame for those bits that are outside your view. I suppose you
could copy to the thread's stack the exception stack frame from the top of the
passed frame to a dummy word on the called functions local stack?

Chris
___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

Re: [PATCH v1 3/5] cpukit/aarch64: Add Exception Manager support

2021-09-01 Thread Kinsey Moore

On 9/1/2021 10:58, Sebastian Huber wrote:

On 01/09/2021 17:48, Sebastian Huber wrote:

So, my proposal would be something like this:

1. Processor jumps to exception prologue

2. Exception prologue saves the context to CPU exception frame

3. Exception prologue calls rtems_fatal() which does not return

For the signal mapping you provide a fatal extension:

1. If the source is not RTEMS_FATAL_SOURCE_EXCEPTION, then return 
(system terminates).


2. If the exception type cannot be handled, then return (system 
terminates).


3. Add a post-switch action to the executing thread.

4. Call _CPU_Exception_return( frame )

The  _CPU_Exception_return( frame ) should:

1. Save the CPU exception return information to the stack of the 
executing thread.


2. Switch to the stack of the executing thread and to thread context 
with interrupts disabled.


3. Do something similar to the interrupt return.

4. The thread dispatch will call the post-switch extension which 
could raise a signal.


This approach avoids a new user extension and it avoids a potentially 
dead code in the exception epilogue.


Chris, I guess you have something like this

_CPU_Exception_return( frame )

in libdebugger currently?

I expected that since libdebugger wasn't built on the fatal error 
extension mechanism that it wasn't suitable for that type of functionality.


One thing I've been trying to avoid with the current approach is manual 
unwinding of the exception stack and the side-effects of other fatal 
error extensions. I suppose I could orchestrate the ordering of existing 
extensions such that recoverable exception handlers run before anything 
else.



Kinsey

___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

Re: [PATCH v1 3/5] cpukit/aarch64: Add Exception Manager support

2021-09-01 Thread Sebastian Huber

On 01/09/2021 17:48, Sebastian Huber wrote:

So, my proposal would be something like this:

1. Processor jumps to exception prologue

2. Exception prologue saves the context to CPU exception frame

3. Exception prologue calls rtems_fatal() which does not return

For the signal mapping you provide a fatal extension:

1. If the source is not RTEMS_FATAL_SOURCE_EXCEPTION, then return 
(system terminates).


2. If the exception type cannot be handled, then return (system 
terminates).


3. Add a post-switch action to the executing thread.

4. Call _CPU_Exception_return( frame )

The  _CPU_Exception_return( frame ) should:

1. Save the CPU exception return information to the stack of the 
executing thread.


2. Switch to the stack of the executing thread and to thread context 
with interrupts disabled.


3. Do something similar to the interrupt return.

4. The thread dispatch will call the post-switch extension which could 
raise a signal.


This approach avoids a new user extension and it avoids a potentially 
dead code in the exception epilogue.


Chris, I guess you have something like this

_CPU_Exception_return( frame )

in libdebugger currently?

--
embedded brains GmbH
Herr Sebastian HUBER
Dornierstr. 4
82178 Puchheim
Germany
email: sebastian.hu...@embedded-brains.de
phone: +49-89-18 94 741 - 16
fax:   +49-89-18 94 741 - 08

Registergericht: Amtsgericht München
Registernummer: HRB 157899
Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
Unsere Datenschutzerklärung finden Sie hier:
https://embedded-brains.de/datenschutzerklaerung/
___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

Re: [PATCH v1 3/5] cpukit/aarch64: Add Exception Manager support

2021-09-01 Thread Sebastian Huber

On 24/08/2021 01:50, Kinsey Moore wrote:

diff --git a/cpukit/score/cpu/aarch64/aarch64-exception-default.c 
b/cpukit/score/cpu/aarch64/aarch64-exception-default.c
index 2ebb3dee9f..e51e9453e1 100644
--- a/cpukit/score/cpu/aarch64/aarch64-exception-default.c
+++ b/cpukit/score/cpu/aarch64/aarch64-exception-default.c
@@ -43,8 +43,61 @@
  
  #include 

  #include 
+#include 
  
  void _AArch64_Exception_default( CPU_Exception_frame *frame )

  {
-  rtems_fatal( RTEMS_FATAL_SOURCE_EXCEPTION, (rtems_fatal_code) frame );
+  if ( rtems_exception_manage( frame ) == false ) {
+rtems_fatal( RTEMS_FATAL_SOURCE_EXCEPTION, (rtems_fatal_code) frame );
+  }
+}


This is exactly the approach I don't like. I don't think we need a new 
user extension for this. We can do the exception to signal mapping also 
in a fatal error extension.


We should avoid changes in the RTEMS API unless it is really necessary. 
 Using an existing extension is preferable to adding new ones.


The normal action in case a non-interrupt exception occurs is to log the 
context and then restart the system. For this, we only need an exception 
prologue which calls rtems_fatal() as robust and safe as possible. In 
particular, it should not use the stack of the context which caused the 
exception. Non-interrupt exceptions in the field are usually due to some 
abnormal program behaviour which usually happens rarely. Getting a good 
context of the error is important. Recursive exceptions due to errors in 
the exception handling are very bad in this respect.


Since rtems_fatal() does not return to the caller, we don't need an 
exception epilogue after the rtems_fatal() call. Such an epilogue would 
be dead code in most systems. I spent a lot of time in the past to avoid 
dead code, so this is one of the reasons why I don't like the proposed 
approach.


If a fatal error extension determined that it is safe to resume 
execution, then it could simply call a new architecture-specific 
function which uses the CPU exception frame to continue execution. This 
function is basically something like the exception epilogue which you 
have on AArch64 right now. The only difference is that it is not 
executed after a return from _AArch64_Exception_default() and instead 
explicitly invoked by a function call, for example 
_CPU_Exception_return( frame ).


So, my proposal would be something like this:

1. Processor jumps to exception prologue

2. Exception prologue saves the context to CPU exception frame

3. Exception prologue calls rtems_fatal() which does not return

For the signal mapping you provide a fatal extension:

1. If the source is not RTEMS_FATAL_SOURCE_EXCEPTION, then return 
(system terminates).


2. If the exception type cannot be handled, then return (system terminates).

3. Add a post-switch action to the executing thread.

4. Call _CPU_Exception_return( frame )

The  _CPU_Exception_return( frame ) should:

1. Save the CPU exception return information to the stack of the 
executing thread.


2. Switch to the stack of the executing thread and to thread context 
with interrupts disabled.


3. Do something similar to the interrupt return.

4. The thread dispatch will call the post-switch extension which could 
raise a signal.


This approach avoids a new user extension and it avoids a potentially 
dead code in the exception epilogue.



--
embedded brains GmbH
Herr Sebastian HUBER
Dornierstr. 4
82178 Puchheim
Germany
email: sebastian.hu...@embedded-brains.de
phone: +49-89-18 94 741 - 16
fax:   +49-89-18 94 741 - 08

Registergericht: Amtsgericht München
Registernummer: HRB 157899
Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
Unsere Datenschutzerklärung finden Sie hier:
https://embedded-brains.de/datenschutzerklaerung/
___
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel