This is the mail archive of the
ecos-patches@sources.redhat.com
mailing list for the eCos project.
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}