This is the mail archive of the ecos-patches@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: SVC SPSR overwritten in Arm HAL


Pierre Habraken wrote:
> 
> Mark Salter wrote:
> > [...]
> > Ahh, right. So, it looks like the branch will have to stay.
> 
> Ok.
> Most of eCos application developers will probably consider the
> (mis-)behavior I described as a feature not as a bug.
> On this assumption, the change I propose has to be conditionally
> compiled (based on a cdl option) and disabled by default.
> I'll prepare a patch and send it together with cdl and change log
> entries. I'll include with this patch the changes I already submitted
> two weeks ago for adding support of user mode programs.

Patch and ChangeLog entries attached.

Pierre
-- 
________________________________________________________________________
Pierre HABRAKEN - mailto:Pierre dot Habraken at imag dot fr
Tél: 04 76 82 72 83 - Fax: 04 76 82 72 87
IMAG-LSR BP72 38402 SAINT MARTIN D'HERES Cedex
________________________________________________________________________
2003-04-18  Pierre Habraken  <Pierre dot Habraken at imag dot fr>

   * cdl/hal_arm.cdl: Added option CYGOPT_HAL_ARM_PRESERVE_SVC_SPSR for
   securing exception and breakpoint processing triggered during
   execution of application specific SWI handlers.
   * src/vectors.S (return_from_exception): Added code to exception
   handling for preserving svc spsr before returning to svc mode.

2003-04-08  Pierre Habraken  <Pierre dot Habraken at imag dot fr>

   * cdl/hal_arm.cdl: Added option CYGOPT_HAL_ARM_WITH_USER_MODE for
   supporting programs running in user mode.
   * include/hal_arch.h: Defined CPSR_USER_MODE.
   * src/hal_mk_defs.c.: Added definition for CPSR_USER_MODE.
   * src/vectors.S (call_exception_handler, return_from_exception,
   handle_IRQ_or_FIQ): Added code to exception handling to allow
   exceptions in user mode.

--- hal/arm/arch/current/cdl/hal_arm.cdl.inst	Tue Aug  6 16:34:04 2002
+++ hal/arm/arch/current/cdl/hal_arm.cdl	Wed Apr 16 09:12:14 2003
@@ -212,6 +212,22 @@
             active."
     }
 
+    cdl_option CYGOPT_HAL_ARM_WITH_USER_MODE {
+        display          "Accept exceptions and irq's occurring in user mode"
+        default_value    0
+        description      "
+            For standalone Redboot based programs running in user mode."
+    }
+
+    cdl_option CYGOPT_HAL_ARM_PRESERVE_SVC_SPSR {
+        display          "Preserve svc spsr before returning to svc mode"
+        default_value    0
+        description      "
+            This option secures exception and breakpoint processing
+            triggered during execution of application specific SWI
+            handlers."
+    }
+
     cdl_component CYGPKG_REDBOOT_ARM_OPTIONS {
         display       "Redboot for ARM options"
         flavor        none
--- hal/arm/arch/current/include/hal_arch.h.inst	Thu Aug 22 14:24:20 2002
+++ hal/arm/arch/current/include/hal_arch.h	Sat Apr  5 18:14:32 2003
@@ -64,6 +64,7 @@
 #define CPSR_IRQ_DISABLE	0x80	// IRQ disabled when =1
 #define CPSR_FIQ_DISABLE	0x40	// FIQ disabled when =1
 #define CPSR_THUMB_ENABLE	0x20	// Thumb mode when =1
+#define CPSR_USER_MODE		0x10
 #define CPSR_FIQ_MODE		0x11
 #define CPSR_IRQ_MODE		0x12
 #define CPSR_SUPERVISOR_MODE	0x13
--- hal/arm/arch/current/src/hal_mk_defs.c.inst	Fri May 24 01:01:42 2002
+++ hal/arm/arch/current/src/hal_mk_defs.c	Sat Apr  5 18:34:25 2003
@@ -109,6 +109,7 @@
     DEFINE(CPSR_IRQ_DISABLE, CPSR_IRQ_DISABLE);
     DEFINE(CPSR_FIQ_DISABLE, CPSR_FIQ_DISABLE);
     DEFINE(CPSR_THUMB_ENABLE, CPSR_THUMB_ENABLE);
+    DEFINE(CPSR_USER_MODE, CPSR_USER_MODE);
     DEFINE(CPSR_IRQ_MODE, CPSR_IRQ_MODE);
     DEFINE(CPSR_FIQ_MODE, CPSR_FIQ_MODE);
     DEFINE(CPSR_SUPERVISOR_MODE, CPSR_SUPERVISOR_MODE);
--- hal/arm/arch/current/src/vectors.S.inst	Thu Aug 29 13:49:49 2002
+++ hal/arm/arch/current/src/vectors.S	Wed Apr 16 09:01:52 2003
@@ -489,7 +489,8 @@
 //
 // Exception handlers
 // Assumption: get here from a non-user context [mode]
-//
+//             except in case of standalone app. running in user mode
+//             (CYGOPT_HAL_ARM_WITH_USER_MODE should have been defined)
         .code   32
 undefined_instruction:
         ldr     sp,.__undef_exception_stack     // get good stack
@@ -579,18 +580,31 @@
         // r4 holds original svc lr, which must also be preserved
         //
 
+
         stmfd   sp!,{r0-r2,r4,r5}       // push svc_sp, svc_lr, vector, psr, pc
         
+#ifdef CYGOPT_HAL_ARM_WITH_USER_MODE
+        // did exception occur in user mode ?
+        and     r2, r1, #CPSR_MODE_BITS
+        cmp     r2, #CPSR_USER_MODE
+        bne     1f
+        stmfd   sp, {r8-r12, sp, lr}^   // get user mode regs
+        nop
+        sub     sp, sp, #4*7
+        bal     2f
+1:
+#endif
         // switch to pre-exception mode to get banked regs
         mov     r0,sp                   // r0 survives mode switch
         mrs     r2,cpsr                 // Save current psr for return
+
         orr     r1,r1,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
         bic     r1,r1,#CPSR_THUMB_ENABLE
         msr     cpsr,r1
         stmfd   r0!,{r8-r12,sp,lr}
         msr     cpsr,r2                 // back to svc mode
         mov     sp,r0                   // update stack pointer
-
+2:
         // now save pre-exception r0-r7 on current stack
         ldmfd   r3,{r0-r5}
         stmfd   sp!,{r0-r7}
@@ -630,26 +644,53 @@
 return_from_exception:
 
         ldr     r0,[sp,#armreg_cpsr]
-        msr     spsr,r0
 
         // return to supervisor mode is simple
         and     r1,r0,#CPSR_MODE_BITS
         cmp     r1,#CPSR_SUPERVISOR_MODE
+
+#ifndef CYGOPT_HAL_ARM_PRESERVE_SVC_SPSR
+        msr     spsr,r0
         ldmeqfd sp,{r0-r14,pc}^
+#else
+        // we must take care of not corrupting the current (svc)
+        // spsr which happens to be also the pre-exception spsr
+        bne     1f
+        // we are returning to svc mode thus we must restore the
+        // pre-exception cpsr before returning to interrupted code
+        msr     cpsr, r0
+        ldmfd   sp, {r0-r14, pc}
+1:
+        // we are not returning to svc mode thus we can safely restore
+        // svc spsr
+        msr     spsr, r0
+#endif
 
+#ifdef CYGOPT_HAL_ARM_WITH_USER_MODE
+        // are we returning to user mode ?
+        and     r2, r1, #CPSR_MODE_BITS
+        cmp     r2, #CPSR_USER_MODE
+        add     r2, sp, #armreg_r8
+        bne     1f
+        ldmfd   r2, {r8-r14}^           // restore user mode regs
+        nop
+        bal     2f
+1:
+#else
+        add     r2, sp, #armreg_r8
+#endif
         //
         // return to other non-user modes is a little trickier
         //
 
         // switch to pre-exception mode and restore r8-r14
-        add     r2,sp,#armreg_r8
         mrs     r1,cpsr
         orr     r0,r0,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
         bic     r0,r0,#CPSR_THUMB_ENABLE
         msr     cpsr,r0
         ldmfd   r2,{r8-r14}
         msr     cpsr, r1        // back to svc mode
-
+2:
         // move sp,lr and pc for final load
         ldr     r0,[sp,#armreg_svcsp]
         str     r0,[sp,#armreg_r8]
@@ -675,6 +716,8 @@
 // Handle device interrupts
 // This is slightly more complicated than the other exception handlers because
 // it needs to interface with the kernel (if present).
+// Assumption: can get here from any mode, including user mode
+// (spurious interrupt while standalone app. is running in user mode)
 
         .code   32
 FIQ:
@@ -722,6 +765,17 @@
 	mov	r4,lr			// save original svc lr
         stmfd   sp!,{r0-r2,r4,r5}       // push svc_sp, svc_lr, vector, psr, pc
 		
+#ifdef CYGOPT_HAL_ARM_WITH_USER_MODE
+        // did exception occur in user mode ?
+        and     r2, r1, #CPSR_MODE_BITS
+        cmp     r2, #CPSR_USER_MODE
+        bne     1f
+        stmfd   sp, {r8-r12, sp, lr}^   // get user mode regs
+        nop
+        sub     sp, sp, #4*7
+        bal     2f
+1:
+#endif
         // switch to pre-exception mode to get banked regs
         mov     r0,sp                   // r0 survives mode switch
         mrs     r2,cpsr                 // Save current psr for return
@@ -731,7 +785,7 @@
         stmfd   r0!,{r8-r12,sp,lr}
         msr     cpsr,r2                 // back to svc mode
         mov     sp,r0                   // update stack pointer
-	
+2:
         // now save pre-exception r0-r7 on current stack
         ldmfd   r3,{r0-r5}
         stmfd   sp!,{r0-r7}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]