Commit b935ae8d authored by Jeffrey Lee's avatar Jeffrey Lee

Fix temporary RMA corruption while inside RTSupport routine

Detail:
  Previously the RTSupport routine would execute in SYS mode, and use assembler veneers to make direct calls to the buffer manager.
  Despite being against the buffer manager spec (only IRQ or SVC should be used, according to PRM 5a), the buffer manager was coping with SYS mode calls fine. However the buffer manager would call DeviceFS, and DeviceFS would then call USBDriver, entering the module via one of CMHG's generic veneers.
  These veneers attempt to switch to SVC mode on entry, but they do so by only interacting with the bottom two bits of the PSR - so the CPU was remaining in SYS mode.
  Although this isn't a problem in and of itself, immediately after the mode change comes some code to set up the static relocation offsets at the SVC stack limit.
  This is done by aligning the stack pointer to a MB boundary. If we were in SVC mode this would be fine, but since we're still in SYS mode we're using a stack that was allocated by SCSISoftUSB and isn't aligned to a boundary at all; thus resulting in two words of RMA being swapped out with something completely different while the USBDriver code executes.
  With RTSupport in ROM this will most likely end up being the first two words of the heap - which is enough to stop OS_Module from manipulating the heap (the heap manager will see it as corrupt), but without causing any lasting damage.
  To solve this issue we now run the entire routine in SVC mode, using the MB-aligned SVC stack that RTSupport provides for us.
  File changes:
  c/global, c/cmodule, h/global - Get rid of the SYS mode stack since we no longer need it
  c/glue, h/glue - Extern RTSupportWrapper so it can be called from the assembler veneer. Tweak RT_Register parameters to pass in the relocation offsets (and no SYS stack)
  s/asm, h/asm - Added asm_RTSupportWrapper to get us into and out of SVC mode around the call to RTSupportWrapper. Also sets up our stack limit & relocation offsets within the SVC stack.
Admin:
  Tested in BCM2835 ROM


Version 0.16. Tagged as 'SCSISoftUSB-0_16'
parent c6ff2236
/* (0.15)
/* (0.16)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 0.15
#define Module_MajorVersion_CMHG 0.16
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 27 Nov 2011
#define Module_Date_CMHG 03 Jun 2012
#define Module_MajorVersion "0.15"
#define Module_Version 15
#define Module_MajorVersion "0.16"
#define Module_Version 16
#define Module_MinorVersion ""
#define Module_Date "27 Nov 2011"
#define Module_Date "03 Jun 2012"
#define Module_ApplicationDate "27-Nov-11"
#define Module_ApplicationDate "03-Jun-12"
#define Module_ComponentName "SCSISoftUSB"
#define Module_ComponentPath "mixed/RiscOS/Sources/HWSupport/SCSI/SCSISoftUSB"
#define Module_FullVersion "0.15"
#define Module_HelpVersion "0.15 (27 Nov 2011)"
#define Module_LibraryVersionInfo "0:15"
#define Module_FullVersion "0.16"
#define Module_HelpVersion "0.16 (03 Jun 2012)"
#define Module_LibraryVersionInfo "0:16"
......@@ -59,7 +59,6 @@ my_usb_device_t *global_TickerList = NULL; /* list of devices using TickerV */
bool global_UseRTSupport = false; /* Use RTSupport instead of TickerV? */
int global_RTSupportPollword = 0; /* RTSupport pollword */
_kernel_stack_chunk *global_RTSupportStack = 0; /* RTSupport stack chunk */
int global_RTSupportHandle = 0; /* RTSupport handle */
callback_type global_CallbackType = callback_NONE; /* Type of our registered callback, if any */
......
......@@ -844,7 +844,7 @@ static void Callback(struct umass_softc *softc, void *void_device, int not_trans
* NONE
*
* Inputs
* r0: R0 value from RTSupport. Unused.
* NONE
*
* Outputs
* NONE
......@@ -853,11 +853,10 @@ static void Callback(struct umass_softc *softc, void *void_device, int not_trans
* Time of next execution. May not return at all if the RTSupport callback is
* no longer needed.
*****************************************************************************/
static __value_in_regs rtsupport_routine_result RTSupportWrapper(void *r0)
__value_in_regs rtsupport_routine_result RTSupportWrapper(void)
{
unsigned int time;
_kernel_oserror *e;
IGNORE(r0);
DEBUGCHAR('>');
/* Make sure IRQs are off. RTSupport will restore the correct state when/if we exit. */
_kernel_irqs_off();
......@@ -924,12 +923,12 @@ static void GetOnTickerV(my_usb_device_t *device)
DEBUGCHAR('+');
_kernel_oserror *e = _swix(RT_Register,_INR(0,7)|_OUT(0),
0,
RTSupportWrapper,
0,
asm_RTSupportWrapper,
*((uint32_t **)global_PrivateWord)+1,
global_PrivateWord,
&global_RTSupportPollword,
((int)global_RTSupportStack)+560,
((int)global_RTSupportStack)+RTSTACK_SIZE,
0,
0,
"SCSISoftUSB:48",
&global_RTSupportHandle);
if(!e)
......
......@@ -211,14 +211,7 @@ _kernel_oserror *module_Init(const char *cmd_tail, int podule_base, void *pw)
version = version<<(zeros*4);
if(version >= 0x0500)
{
global_RTSupportStack = calloc(1, RTSTACK_SIZE);
if(global_RTSupportStack)
{
global_UseRTSupport = true;
global_RTSupportStack->sc_mark = 0xF60690FF;
global_RTSupportStack->sc_size = RTSTACK_SIZE;
memcpy(global_RTSupportStack+1,_kernel_current_stack_chunk()+1,28);
}
global_UseRTSupport = true;
}
}
if(!global_UseRTSupport)
......@@ -316,8 +309,6 @@ _kernel_oserror *module_Final(int fatal, int podule, void *pw)
_swix(RT_Deregister, _INR(0,1),
0,
global_RTSupportHandle);
if(global_RTSupportStack)
free(global_RTSupportStack);
_swix(OS_Release, _INR(0,2),
UpCallV,
module_upcallv_handler,
......
......@@ -124,6 +124,26 @@ extern uint32_t asm_CallBufferManager(uint32_t reason, uint32_t buffer_id, void
*****************************************************************************/
extern void asm_UpCallHandler(void);
/*****************************************************************************
* asm_RTSupportWrapper
*
* Wrapper for RTSupportWrapper, to get us out of SYS mode and into SVC mode
* (required so we can safely use the other asm calls)
*
* Assumptions
* NONE
*
* Inputs
* Pointer to relocation offsets
*
* Outputs
* NONE
*
* Returns
* Details of next call, from RTSupportWrapper
*****************************************************************************/
extern void asm_RTSupportWrapper(uint32_t *reloc);
#endif /* end of sentry #ifdef */
/*****************************************************************************
......
......@@ -185,7 +185,6 @@ extern my_usb_device_t *global_DeviceList; /* list of usb device info */
extern my_usb_device_t *global_TickerList; /* list of devices using TickerV/RTSupport */
extern bool global_UseRTSupport; /* Use RTSupport module for scheduling, not TickerV */
extern int global_RTSupportPollword; /* RTSupport pollword */
extern _kernel_stack_chunk *global_RTSupportStack; /* RTSupport stack chunk */
extern int global_RTSupportHandle; /* RTSupport handle */
extern callback_type global_CallbackType; /* Type of our registered callback, if any */
extern uint32_t global_PopUpDelay; /* Delay before SCSIFS gets told about new devices */
......
......@@ -209,6 +209,27 @@ extern void glue_ReopenStream(uint32_t file_handle);
*****************************************************************************/
extern void glue_BufferThresholdCheck(uint32_t buffer,bool filling);
/*****************************************************************************
* RTSupportWrapper
*
* Wrapper function that sits between the RTSupport module and
* module_TickerVHandler
*
* Assumptions
* NONE
*
* Inputs
* NONE
*
* Outputs
* NONE
*
* Returns
* Time of next execution. May not return at all if the RTSupport callback is
* no longer needed.
*****************************************************************************/
__value_in_regs rtsupport_routine_result RTSupportWrapper(void);
#endif /* end of sentry #ifdef */
/*****************************************************************************
......
......@@ -38,6 +38,8 @@
EXPORT asm_DoTransferCompleteCallback
EXPORT asm_CallBufferManager
EXPORT asm_UpCallHandler
EXPORT asm_RTSupportWrapper
IMPORT RTSupportWrapper
; extern void asm_DoTransferCompleteCallback(_kernel_oserror *error,
; uint32_t status_byte,
......@@ -80,4 +82,21 @@ asm_UpCallHandler
STREQ r4, [r12]
MOV pc, lr
; extern __value_in_regs rtsupport_routine_result asm_RTSupportWrapper(uint32_t *reloc)
; Wrapper for RTSupportWrapper to get us out of SYS mode and into SVC mode
; (required so we can safely use the other asm calls)
; Note - no need for us to preserve the current relocation offsets in the stack,
; RTSupport will handle that for us
asm_RTSupportWrapper
LDMIA r0, {r0-r1} ; Load relocation offsets
MSR CPSR_c, #SVC32_mode
MOV r10, r13, LSR #20
MOV r10, r10, LSL #20
STMIA r10, {r0-r1}
ADD r10, r10, #540
BL RTSupportWrapper
MSR CPSR_c, #SYS32_mode ; Must return to RTSupport in SYS mode
MOV pc, lr
END
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment