Mercurial > flash_v2
changeset 1002:609c8b1447ee
HAL enhancements from Pierre Habraken
| author | msalter |
|---|---|
| date | Tue, 06 May 2003 21:00:18 +0000 |
| parents | b8e01d85e2d4 |
| children | fae4fcdd86d2 |
| files | packages/hal/arm/arch/current/ChangeLog packages/hal/arm/arch/current/cdl/hal_arm.cdl packages/hal/arm/arch/current/include/hal_arch.h packages/hal/arm/arch/current/src/arm_stub.c packages/hal/arm/arch/current/src/hal_mk_defs.c packages/hal/arm/arch/current/src/vectors.S packages/hal/common/current/ChangeLog packages/hal/common/current/src/generic-stub.c packages/hal/common/current/src/hal_stub.c packages/redboot/current/ChangeLog packages/redboot/current/cdl/redboot.cdl packages/redboot/current/src/main.c packages/redboot/current/src/syscall.c |
| diffstat | 13 files changed, 217 insertions(+), 35 deletions(-) [+] |
line wrap: on
line diff
--- a/packages/hal/arm/arch/current/ChangeLog +++ b/packages/hal/arm/arch/current/ChangeLog @@ -1,3 +1,21 @@ +2003-05-06 Pierre Habraken <Pierre.Habraken@imag.fr> + + * src/arm_stub.c (target_ins, target_thumb_ins): Added code to + enable stepping into swi instructions. + + * 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. Added option + CYGOPT_HAL_ARM_WITH_USER_MODE for supporting programs running in + user mode. + * src/vectors.S (return_from_exception): Added code to exception + handling for preserving svc spsr before returning to svc mode. + Added code to allow exceptions in user mode. + (call_exception_handler, handle_IRQ_or_FIQ): Added code to allow + exceptions in user mode. + * include/hal_arch.h: Defined CPSR_USER_MODE. + * src/hal_mk_defs.c.: Added definition for CPSR_USER_MODE. + 2003-04-30 Jonathan Larmour <jifl@eCosCentric.com> * src/vectors.S (handle_IRQ_or_FIQ): Tweak below to be conditional on
--- a/packages/hal/arm/arch/current/cdl/hal_arm.cdl +++ b/packages/hal/arm/arch/current/cdl/hal_arm.cdl @@ -212,6 +212,22 @@ cdl_package CYGPKG_HAL_ARM { 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
--- a/packages/hal/arm/arch/current/include/hal_arch.h +++ b/packages/hal/arm/arch/current/include/hal_arch.h @@ -11,7 +11,7 @@ //####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free @@ -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
--- a/packages/hal/arm/arch/current/src/arm_stub.c +++ b/packages/hal/arm/arch/current/src/arm_stub.c @@ -8,7 +8,7 @@ //####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free @@ -528,7 +528,12 @@ target_ins(unsigned long *pc, unsigned l } } case 0x3: // Coprocessor & SWI - return (pc+1); + if (((ins & 0x03000000) == 0x03000000) && ins_will_execute(ins)) { + // SWI + return (CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT * 4); + } else { + return (pc+1); + } default: // Never reached - but fixes compiler warning. return 0; @@ -570,10 +575,13 @@ target_thumb_ins(unsigned long pc, unsig } break; case 0xd: - // Bcc + // Bcc | SWI // Use ARM function to check condition arm_ins = ((unsigned long)(ins & 0x0f00)) << 20; - if (ins_will_execute(arm_ins)) { + if ((arm_ins & 0xF0000000) == 0xF0000000) { + // SWI + new_pc = CYGNUM_HAL_VECTOR_SOFTWARE_INTERRUPT * 4; + } else if (ins_will_execute(arm_ins)) { offset = (ins & 0x00FF) << 1; if (ins & 0x0080) offset |= 0xFFFFFE00; // sign extend new_pc = MAKE_THUMB_ADDR((unsigned long)(pc+4) + offset);
--- a/packages/hal/arm/arch/current/src/hal_mk_defs.c +++ b/packages/hal/arm/arch/current/src/hal_mk_defs.c @@ -8,7 +8,7 @@ //####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free @@ -109,6 +109,7 @@ main(void) 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);
--- a/packages/hal/arm/arch/current/src/vectors.S +++ b/packages/hal/arm/arch/current/src/vectors.S @@ -8,7 +8,7 @@ //####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free @@ -490,6 +490,8 @@ init_done: // // 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: @@ -582,6 +584,17 @@ 10: 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 @@ -591,7 +604,7 @@ 10: 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} @@ -636,14 +649,42 @@ return_from_exception: // 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 @@ -651,6 +692,7 @@ return_from_exception: 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] @@ -676,6 +718,8 @@ return_from_exception: // 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: @@ -723,6 +767,17 @@ handle_IRQ_or_FIQ: 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 @@ -733,6 +788,7 @@ handle_IRQ_or_FIQ: 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}
--- a/packages/hal/common/current/ChangeLog +++ b/packages/hal/common/current/ChangeLog @@ -1,3 +1,13 @@ +2003-05-06 Mark Salter <msalter@redhat.com> + + * src/hal_stub.c (handle_exception_exit): Call sys_profile_reset from + here. Setup to return through return_from_stub() when appropriate. + (return_from_stub): New function to call CYGACC_CALL_IF_MONITOR_RETURN + from thread context. + + * src/generic-stub.c (__handle_exception): Call exit_vec if + hal_syscall_handler returns negative number. + 2003-04-08 Mark Salter <msalter@redhat.com> * src/hal_misc.c (hal_default_isr): Allow HAL to override default
--- a/packages/hal/common/current/src/generic-stub.c +++ b/packages/hal/common/current/src/generic-stub.c @@ -907,8 +907,11 @@ void if (__is_bsp_syscall()) { sigval = hal_syscall_handler(); - if (0 == sigval) + if (sigval <= 0) { + if (sigval < 0) + __process_exit_vec (); + if (__init_vec != NULL) __init_vec (); return; @@ -1436,12 +1439,6 @@ int #ifdef __ECOS__ hal_flush_output(); #endif -#ifdef CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF - { // Reset the timer to default and cancel any callback - extern void sys_profile_reset(void); - sys_profile_reset(); - } -#endif // CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF __process_exit_vec (); return -1;
--- a/packages/hal/common/current/src/hal_stub.c +++ b/packages/hal/common/current/src/hal_stub.c @@ -8,7 +8,7 @@ //####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. -// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free @@ -97,7 +97,9 @@ HAL_SavedRegisters *_hal_registers; target_register_t registers[HAL_STUB_REGISTERS_SIZE]; target_register_t alt_registers[HAL_STUB_REGISTERS_SIZE] ; // Thread or saved process state target_register_t * _registers = registers; // Pointer to current set of registers +#ifndef CYGPKG_REDBOOT target_register_t orig_registers[HAL_STUB_REGISTERS_SIZE]; // Registers to get back to original state +#endif #if defined(HAL_STUB_HW_WATCHPOINT) || defined(HAL_STUB_HW_BREAKPOINT) static int _hw_stop_reason; // Reason we were stopped by hw. @@ -378,21 +380,42 @@ interruptible(int state) int cyg_hal_gdb_break; #endif +#ifdef CYGPKG_REDBOOT +// Trampoline for returning to RedBoot from exception/stub code +static void +return_from_stub(int exit_status) +{ + CYGACC_CALL_IF_MONITOR_RETURN(exit_status); +} +#endif + // Called at stub *kill* static void handle_exception_exit( void ) { +#ifdef CYGPKG_REDBOOT +#ifdef CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF + { // Reset the timer to default and cancel any callback + extern void sys_profile_reset(void); + sys_profile_reset(); + } +#endif // CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF + set_pc((target_register_t)return_from_stub); +#else int i; for (i = 0; i < (sizeof(registers)/sizeof(registers[0])); i++) registers[i] = orig_registers[i]; +#endif } // Called at stub *entry* static void handle_exception_cleanup( void ) { +#ifndef CYGPKG_REDBOOT static int orig_registers_set = 0; +#endif interruptible(0); @@ -401,6 +424,7 @@ handle_exception_cleanup( void ) HAL_GET_GDB_REGISTERS(®isters[0], _hal_registers); _registers = ®isters[0]; +#ifndef CYGPKG_REDBOOT if (!orig_registers_set) { int i; for (i = 0; i < (sizeof(registers)/sizeof(registers[0])); i++) @@ -411,6 +435,7 @@ handle_exception_cleanup( void ) _registers = ®isters[0]; orig_registers_set = 1; } +#endif #ifdef HAL_STUB_PLATFORM_STUBS_FIXUP // Some architectures may need to fix the PC in case of a partial
--- a/packages/redboot/current/ChangeLog +++ b/packages/redboot/current/ChangeLog @@ -1,3 +1,26 @@ +2003-05-06 Mark Salter <msalter@redhat.com> + + * src/main.c (cyg_start): Clear gdb_active when returning from stub. + +2003-05-06 Pierre Habraken <Pierre.Habraken@imag.fr> + + * cdl/redboot.cdl: Added option + CYGOPT_REDBOOT_BSP_SYSCALLS_EXIT_WITHOUT_TRAP for enabling (possibly + single shot) programs to exit and return a termination status as + their normal behavior (i.e. without raising a SIGTRAP). + * src/syscall.c (__do_syscall): Added conditionally compiled code + to SYS_exit for returning to RedBoot main loop without raising a + SIGTRAP, even when the calling program is not being debugged. + * src/main.c (cyg_start): Added code (following Jonathan Larmour's + and Mark Salter's suggestions) to RedBoot main loop: a (context) + savepoint is created before the thread of control is transferred to + gdb stubs (through a trampoline procedure). This savepoint enables + the stubs to return control back to the main loop by calling the + return_to_redboot procedure (macro CYGACC_CALL_IF_MONITOR_RETURN). + Procedure go_trampoline and variables go_saved_context and + go_return_status have been respectively renamed to trampoline, + saved_context and return_status. + 2003-04-23 Chris Garry <cgarry@sweeneydesign.co.uk> * src/flash.c: Only perform RAM check in fis load command when
--- a/packages/redboot/current/cdl/redboot.cdl +++ b/packages/redboot/current/cdl/redboot.cdl @@ -861,6 +861,15 @@ cdl_package CYGPKG_REDBOOT { display "Does the HAL support 'gprof' profiling?" no_define } + + cdl_option CYGOPT_REDBOOT_BSP_SYSCALLS_EXIT_WITHOUT_TRAP { + display "Do not raise SIGTRAP when program exits" + default_value 0 + description " + For some (single shot) newlib based programs, + exiting and returning a termination status may be + the normal expected behavior." + } } cdl_component CYGOPT_REDBOOT_FIS_ZLIB_COMMON_BUFFER {
--- a/packages/redboot/current/src/main.c +++ b/packages/redboot/current/src/main.c @@ -80,9 +80,19 @@ extern void breakpoint(void); // Builtin Self Test (BIST) externC void bist(void); -// Return path for code run from a go command +// Path to code run from a go command or to GDB stubs +static void trampoline(unsigned long entry); + +// Return path for code run from a go command or for GDB stubs static void return_to_redboot(int status); +// Address of area where current context is saved before executing +// trampoline procedure +static void * saved_context; + +// Status returned after trampoline execution +static int return_status; + // CLI command processing (defined in this file) RedBoot_cmd("version", @@ -316,11 +326,16 @@ cyg_start(void) } CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); -#ifdef HAL_ARCH_PROGRAM_NEW_STACK - HAL_ARCH_PROGRAM_NEW_STACK(breakpoint); -#else - breakpoint(); // Get GDB stubs started, with a proper environment, etc. -#endif + + // set up a temporary context that will take us to the trampoline + HAL_THREAD_INIT_CONTEXT((CYG_ADDRESS)workspace_end, + breakpoint, trampoline, 0); + + // switch context to trampoline (get GDB stubs started) + HAL_THREAD_SWITCH_CONTEXT(&saved_context, &workspace_end); + + gdb_active = false; + dbgchan = CYGACC_CALL_IF_SET_DEBUG_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); CYGACC_CALL_IF_SET_CONSOLE_COMM(dbgchan); } else @@ -388,11 +403,8 @@ do_help(int argc, char *argv[]) return; } -static void * go_saved_context; -static int go_return_status; - static void -go_trampoline(unsigned long entry) +trampoline(unsigned long entry) { typedef void code_fun(void); code_fun *fun = (code_fun *)entry; @@ -405,6 +417,8 @@ go_trampoline(unsigned long entry) #else (*fun)(); #endif + + HAL_THREAD_LOAD_CONTEXT(&saved_context); } static void @@ -412,8 +426,8 @@ return_to_redboot(int status) { CYGARC_HAL_SAVE_GP(); - go_return_status = status; - HAL_THREAD_LOAD_CONTEXT(&go_saved_context); + return_status = status; + HAL_THREAD_LOAD_CONTEXT(&saved_context); // never returns // need this to balance above CYGARC_HAL_SAVE_GP on @@ -500,10 +514,10 @@ do_go(int argc, char *argv[]) HAL_DCACHE_INVALIDATE_ALL(); // set up a temporary context that will take us to the trampoline - HAL_THREAD_INIT_CONTEXT((CYG_ADDRESS)workspace_end, entry, go_trampoline, 0); + HAL_THREAD_INIT_CONTEXT((CYG_ADDRESS)workspace_end, entry, trampoline, 0); // switch context to trampoline - HAL_THREAD_SWITCH_CONTEXT(&go_saved_context, &workspace_end); + HAL_THREAD_SWITCH_CONTEXT(&saved_context, &workspace_end); // we get back here by way of return_to_redboot() @@ -517,7 +531,7 @@ do_go(int argc, char *argv[]) HAL_RESTORE_INTERRUPTS(oldints); - diag_printf("\nProgram completed with status %d\n", go_return_status); + diag_printf("\nProgram completed with status %d\n", return_status); } #ifdef HAL_PLATFORM_RESET
--- a/packages/redboot/current/src/syscall.c +++ b/packages/redboot/current/src/syscall.c @@ -631,12 +631,16 @@ CYG_ADDRWORD break; case SYS_exit: + *sig = -1; // signal exit + err = arg1; + if (gdb_active) { +#ifdef CYGOPT_REDBOOT_BSP_SYSCALLS_EXIT_WITHOUT_TRAP + __send_exit_status((int)arg1); +#else *sig = SIGTRAP; err = func; - } else { - CYGACC_CALL_IF_MONITOR_RETURN(arg1); - // never returns +#endif // CYGOPT_REDBOOT_BSP_SYSCALLS_EXIT_WITHOUT_TRAP } break;
