Skip to content

Commit 0203dea

Browse files
authored
Added replacement for the Boot ROM _xtos_set_exception_handler (#7820)
Added replacement for the Boot ROM `_xtos_set_exception_handler` to handle installing our replacement `_xtos_c_wrapper_handler`. Simplified install in the non 32-bit exception module to make use of the improved `_xtos_set_exception_handler` Reorganized and improved comments.
1 parent 07241dd commit 0203dea

File tree

3 files changed

+126
-41
lines changed

3 files changed

+126
-41
lines changed

Diff for: cores/esp8266/core_esp8266_non32xfer.cpp

+5-36
Original file line numberDiff line numberDiff line change
@@ -200,50 +200,19 @@ IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef, int cau
200200
}
201201

202202
/*
203-
An issue, the Boot ROM "C" wrapper for exception handlers,
204-
_xtos_c_wrapper_handler, turns interrupts back on. To address this issue we
205-
use our replacement in file `exc-c-wrapper-handler.S`.
206-
207-
An overview, of an exception at entry: New interrupts are blocked by EXCM
208-
being set. Once cleared, interrupts above the current INTLEVEL and exceptions
209-
(w/o creating a DoubleException) can occur.
210-
211-
Using our replacement for _xtos_c_wrapper_handler, INTLEVEL is raised to 15
212-
with EXCM cleared.
213-
214-
The original Boot ROM `_xtos_c_wrapper_handler` would set INTLEVEL to 1 with
215-
EXCM cleared, saved registers, then do a `rsil 0`, and called the registered
216-
"C" Exception handler with interrupts fully enabled! Our replacement keeps
217-
INTLEVEL at 15. This is needed to support the Arduino model of interrupts
218-
disabled while an ISR runs.
219-
220-
And we also need it for umm_malloc to work safely with an IRAM heap from an
221-
ISR call. While malloc() will supply DRAM for all allocation from an ISR,
222-
we want free() to safely operate from an ISR to avoid a leak potential.
223-
224-
This replacement "C" Wrapper is only applied to this exception handler.
203+
To operate reliably, this module requires the new
204+
`_xtos_set_exception_handler` from `exc-sethandler.cpp` and
205+
`_xtos_c_wrapper_handler` from `exc-c-wrapper-handler.S`. See comment block in
206+
`exc-sethandler.cpp` for details on issues with interrupts being enabled by
207+
"C" wrapper.
225208
*/
226-
227-
#define ROM_xtos_c_wrapper_handler (reinterpret_cast<_xtos_handler>(0x40000598))
228-
229-
static void _set_exception_handler_wrapper(int cause) {
230-
_xtos_handler old_wrapper = _xtos_exc_handler_table[cause];
231-
if (old_wrapper == ROM_xtos_c_wrapper_handler) {
232-
_xtos_exc_handler_table[cause] = _xtos_c_wrapper_handler;
233-
}
234-
}
235-
236209
void install_non32xfer_exception_handler(void) __attribute__((weak));
237210
void install_non32xfer_exception_handler(void) {
238211
if (NULL == old_c_handler) {
239212
// Set the "C" exception handler the wrapper will call
240213
old_c_handler =
241214
_xtos_set_exception_handler(EXCCAUSE_LOAD_STORE_ERROR,
242215
non32xfer_exception_handler);
243-
244-
// Set the replacement ASM based exception "C" wrapper function which will
245-
// be calling `non32xfer_exception_handler`.
246-
_set_exception_handler_wrapper(EXCCAUSE_LOAD_STORE_ERROR);
247216
}
248217
}
249218

Diff for: cores/esp8266/exc-c-wrapper-handler.S

+8-5
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,12 @@ _xtos_c_wrapper_handler:
168168
rsync // wait for WSR to PS to complete
169169
rsr a12, SAR
170170

171-
// @mhightower83 - I think after the next instruction we have the potential of
172-
// loosing UEXC_excvaddr Which the earlier comment said we need to preserve for
173-
// the exception handler.
171+
// @mhightower83 - I think, after the next instruction, we have the potential of
172+
// losing UEXC_excvaddr. Which the earlier comment said we need to preserve for
173+
// the exception handler. We keep interrupts off when calling the "C" exception
174+
// handler. For the use cases that I am looking at, this is a must. If there are
175+
// future use cases that need interrupts enabled, those "C" exception handlers
176+
// can turn them on.
174177
//
175178
// rsil a13, 0
176179

@@ -192,8 +195,8 @@ _xtos_c_wrapper_handler:
192195
// load early - saves two cycles - @mhightower83
193196
movi a0, _xtos_return_from_exc
194197

195-
// For compatibility with Arduino interrupt architecture, we keep interrupts 100%
196-
// disabled.
198+
// @mhightower83 - For compatibility with Arduino interrupt architecture, we
199+
// keep interrupts 100% disabled.
197200
// /*
198201
// * Disable interrupts while returning from the pseudo-CALL setup above,
199202
// * for the same reason they were disabled while doing the pseudo-CALL:

Diff for: cores/esp8266/exc-sethandler.cpp

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
* Adaptation of _xtos_set_exception_handler for Arduino ESP8266 core
3+
*
4+
* This replacement for the Boot ROM `_xtos_set_exception_handler` is used to
5+
* install our replacement `_xtos_c_wrapper_handler`. This change protects the
6+
* value of `excvaddr` from corruption.
7+
*
8+
*
9+
* Details
10+
*
11+
* The issue, the Boot ROM "C" wrapper for exception handlers,
12+
* `_xtos_c_wrapper_handler`, turns interrupts back on. This leaves `excvaddr`
13+
* exposed to possible overwrite before it is read. For example, if an interrupt
14+
* is taken during the exception handler processing and the ISR handler
15+
* generates a new exception, the original value of `excvaddr` is lost. To
16+
* address this issue we have a replacement `_xtos_c_wrapper_handler` in file
17+
* `exc-c-wrapper-handler.S`.
18+
*
19+
* An overview, of an exception at entry: New interrupts are blocked by EXCM
20+
* being set. Once cleared, interrupts above the current INTLEVEL and exceptions
21+
* (w/o creating a DoubleException) can occur.
22+
*
23+
* Using our replacement for `_xtos_c_wrapper_handler`, INTLEVEL is raised to 15
24+
* with EXCM cleared.
25+
*
26+
* The original Boot ROM `_xtos_c_wrapper_handler` at entry would set INTLEVEL
27+
* to 3 with EXCM cleared, save registers, then do a `rsil 0` (interrupts fully
28+
* enabled!) just before calling the registered "C" Exception handler. Our
29+
* replacement keeps INTLEVEL at 15. This is needed to support the Arduino model
30+
* of interrupts disabled while an ISR runs.
31+
*
32+
* And we also need it for umm_malloc to work safely with an IRAM heap from an
33+
* ISR call. While malloc() will supply DRAM for all allocation from an ISR, we
34+
* want free() to safely operate from an ISR to avoid a leak potential.
35+
*
36+
* If an exception handler needs interrupts enabled, it would be done after it
37+
* has consumed the value of `excvaddr`. Whether such action is safe is left to
38+
* the exception handler writer to determine. However, with our current
39+
* architecture, I am not convinced it can be done safely.
40+
*
41+
*/
42+
43+
#if defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP) || defined(NEW_EXC_C_WRAPPER)
44+
45+
/*
46+
* The original module source code came from:
47+
* https://github.com/qca/open-ath9k-htc-firmware/blob/master/sboot/magpie_1_1/sboot/athos/src/xtos/exc-sethandler.c
48+
*
49+
* It has been revised to use Arduino ESP8266 core includes, types, and
50+
* formating.
51+
*/
52+
53+
/* exc-sethandler.c - register an exception handler in XTOS */
54+
55+
/*
56+
* Copyright (c) 1999-2006 Tensilica Inc.
57+
*
58+
* Permission is hereby granted, free of charge, to any person obtaining
59+
* a copy of this software and associated documentation files (the
60+
* "Software"), to deal in the Software without restriction, including
61+
* without limitation the rights to use, copy, modify, merge, publish,
62+
* distribute, sublicense, and/or sell copies of the Software, and to
63+
* permit persons to whom the Software is furnished to do so, subject to
64+
* the following conditions:
65+
*
66+
* The above copyright notice and this permission notice shall be included
67+
* in all copies or substantial portions of the Software.
68+
*
69+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
70+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
71+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
72+
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
73+
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
74+
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
75+
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
76+
*/
77+
78+
#include <Arduino.h>
79+
#include "esp8266_undocumented.h"
80+
81+
extern "C" {
82+
83+
/*
84+
* Register a C handler for the specified general exception
85+
* (specified EXCCAUSE value).
86+
*/
87+
fn_c_exception_handler_t _xtos_set_exception_handler(int cause, fn_c_exception_handler_t fn)
88+
{
89+
fn_c_exception_handler_t ret;
90+
91+
if( (unsigned) cause >= XCHAL_EXCCAUSE_NUM )
92+
return 0;
93+
94+
if( fn == 0 )
95+
fn = &_xtos_p_none;
96+
97+
ret = _xtos_c_handler_table[cause];
98+
99+
_xtos_exc_handler_table[cause] = ( (fn == &_xtos_p_none)
100+
? &_xtos_unhandled_exception
101+
: &_xtos_c_wrapper_handler );
102+
103+
_xtos_c_handler_table[cause] = fn;
104+
105+
if( ret == &_xtos_p_none )
106+
ret = 0;
107+
108+
return ret;
109+
}
110+
111+
};
112+
113+
#endif

0 commit comments

Comments
 (0)