📄 dabort.txt
字号:
A Standard Data Abort Handler Veneer
====================================
Copyright 1997 Advanced RISC Machines Limited. All rights reserved.
Author: David Seal
Change history
==============
Revision 0.1 [16 Oct 1997] --- Initial draft version.
Revision 0.2 [31 Oct 1997] --- Review comments incorporated.
Revision 0.3 [04 Nov 1997] --- "SuptThumb" option becomes supported.
Revision 0.4 [07 Nov 1997] --- Change "ReturnUndef" to string, to allow
address specification.
Revision 0.5 [28 Nov 1997] --- Remove unwanted indirection in
"ReturnToNext" mechanism.
Sept 00 : Minor edits for ADS 1.1 release
Introduction
============
Data abort handling on the ARM is quite complex by now, due to a number of
factors:
* Differences between processors' abort models, with regard to base register
writeback for an aborted instruction - from ARM6 to the present, we have
had three different abort models used.
* The growth in the number of classes of load/store instruction that need to
be dealt with. For ARM6, the instructions concerned were (in groups with
similar properties from the point of view of abort handling):
LDR/LDRB/LDRBT/LDRT/STR/STRB/STRBT/STRT (12-bit immediate offset)
LDR/LDRB/LDRBT/LDRT/STR/STRB/STRBT/STRT (shifted register offset)
SWP/SWPB (no offset)
LDM/STM (offset derived from 16-bit register list)
LDC/STC (8-bit immediate offset, times 4)
By ARM7TDMI/ARM9TDMI, this list is augmented by:
LDRH/LDRSB/LDRSH/STRH (8-bit immediate offset)
LDRH/LDRSB/LDRSH/STRH (register offset)
Thumb LDM/STM (offset derived from 8-bit register list)
Thumb PUSH/POP (offset derived from 9-bit register list)
Thumb LDR/STR (5-bit immediate offset, times 4)
Thumb LDR(sp)/LDR(pc)/STR(sp) (8-bit immediate offset, times 4)
Thumb LDRH/STRH (5-bit immediate offset, times 2)
Thumb LDRB/STRB (5-bit immediate offset)
Thumb LDR/LDRB/LDRH/LDRSB/LDRSH/STR/STRB/STRH (register offset)
* Complications due to banked registers - the data abort handler must make
certain that it is working with the correct version of a register.
* Complications due to the PC being in the main register set, yet not
behaving quite like a normal register. These are mostly alleviated by
architectural rules prohibiting writeback to the base register if it is
R15, but still give rise to special cases in the abort handler code to
prevent out-of-control behaviour if such an instruction is executed.
* Complications due to the possibility of the offset register being the same
as the base register, which can lead to the original base register value
not being reconstructible if writeback occurs. The worst cases of this
occur with post-indexing and make it impossible to recover from the abort;
these are definitely architecturally undefined ("UNPREDICTABLE"). Others
occur with pre-indexing and require special-case handling in the data
abort handler; their architectural status is unclear at the time of
writing. (Basically, the ARM Architecture Reference Manual says they are
UNPREDICTABLE, but nothing else says this or tries to enforce this status.
This leaves it unclear whether this is the result of a mis-edit to the ARM
ARM, and leaves the possibility open that such instructions are being used
in real code.)
* Complications due to possible interactions with other exceptions, such
as "what happens if exception X occurs here?" or "how long is it
acceptable to leave interrupts disabled?".
Beyond these "processor core" considerations, there will usually be other
OS-specific ones: e.g. whether this is an abort that can be recovered from
by adjusting the memory map appropriately, and if so, how that adjustment
should be done. These can vary from something comparatively simple such as
adjusting the memory access controls in an MMU or Protection Unit, to very
complex operations such as mapping in a file across an unreliable network.
In addition, the data abort exception is entered in a fashion that is
unlikely to be compatible with any procedure calling standard. Even in the
simpler cases of OS-specific adjustment of the memory map, it is likely
to be complex enough that implementing (most of) it in a high-level language
is highly desirable: this means that an assembly-language "veneer" is needed
to translate the data abort exception into a procedure call. In its simplest
form, such a veneer basically just dumps the processor state into a memory
area, calls a high level language routine with this memory area as a
parameter and restores the processor state from the memory area when the
procedure returns. This leaves the OS-specific code to deal with all the
"processor core" details listed above as well as its own complications.
The purpose of this document is to propose and specify a somewhat more
complicated veneer, the purpose of which is to insulate the OS-specific code
from the processor core considerations. In essence, it will perform
processor-core-specific tidy-up operations (e.g. base register restoration)
and checks (e.g. for instructions that cannot be recovered from) before
calling the OS-specific code, and may use more than one strategy for
returning to the original program after the OS-specific code returns (this
would be necessary e.g. if it is required to handle the pre-indexing base
register = offset register cases referred to above).
The overall scheme is therefore along the lines of:
Original ----------------+----------------------+--------------------
instruction | Aborting instruction |
stream ----------------+----------------------+--------------------
/ \ \
/ \ \ Recovery by
/ \ \ emulation
/ \ --<----------
--<---- \ \
/ Data abort --<--------------------------------\
/ trap Recovery by instruction retry \
/ \
+-----------+---------------+-----------+------------------+
New veneer | Dump | Processor- | Procedure | Choose & perform |
invocation | processor | core-specific | call to | data abort |
| state | tidy-ups | OS code | recovery actions |
+-----------+---------------+-----------+------------------+
/ \
/ \
--<------------- --<--------
/ Passing a standardised Procedure \
/ set of parameters return \
/ \
+--------------------------------------------------+
Main OS code | OS-specific handler for data aborts |
+--------------------------------------------------+
The advantages of this would be:
* The standard ones of "divide and conquer": with the veneer handling the
processor core's data abort considerations and the OS-specific code
handling the wider system issues, each is likely to be simpler and easier
to implement.
* Easier upgrade to a new processor core: only the veneer is liable to need
changing. Furthermore, the processor options the veneer need to be able to
deal with are quite tightly defined architecturally, which means that it
should not need to be changed frequently. (The most likely changes are
upgrades to deal with new instructions being added to the instruction set
- e.g. the motivation for this particular proposal is a customer wanting a
data abort handler that can deal with Thumb instructions.)
* Fewer potential problems due to errors in data abort handling - it is an
easy area to make mistakes in if you're not very familiar with the
architecture (two data abort handlers I looked at while considering this
proposal both had significant bugs or limitations in them, for instance).
Specification
=============
The data abort veneer will be provided as a single assembler source file,
which is assembled appropriately for the system into which it is to be
linked. It assembles as a single code area: all variables that it needs are
either held in registers or defined elsewhere in the system and made
available to the data abort veneer via suitable linking.
There will also be an associated C header file, which defines some symbolic
constants used for OS communication with the data abort veneer. As supplied,
this file will not be able to contain function prototypes for the function
calls described below, due to the fact that the correct prototypes depend
strongly on the assembly-time options used. Users are however encouraged to
generate and use the appropriate prototypes for their selection of
assembly-time options.
General Rules about Assembly-time Options
-----------------------------------------
The assembly-time options described in the following sections can be invoked
in two ways:
1) Via command-line -PreDefine options.
2) By producing a system-specific "options file" which defines and sets the
appropriate assembly-time variables (with GBLL/SETL or GBLS/SETS
directives as appropriate), then INCLUDEs the main assembler source file.
For clarity and to save space, this document is written on the assumption
that method 1) is being used. To use method 2) on some or all of the
options, just translate each -PreDefine option into the corresponding
GBLx/SETx pair in the options file. Note also that in one case, a macro name
can be specified by an option: this macro cannot be defined on the command
line, and thus this possibility can only be used by defining the macro in an
options (or similar) file.
All options that must be specified are indicated as such in the text.
Otherwise, logical options have their non-default value indicated in the
option syntax, with the default being the opposite choice to the one shown,
and other types of option have their default value indicated in the text.
All options whose values are to be treated as assembler labels, area names,
etc. (e.g. the veneer entry point) will be subject to some standard
pre-processing. The purpose of this is to ensure that the symbol actually
used is surrounded by a pair of vertical bars ("|"), to allow the widest
possible range of characters in the symbol. If the symbol as supplied is
already surrounded by vertical bars, nothing is done; otherwise, vertical
bars are added before and after it. (It is an error for the symbol as
supplied to contain vertical bar characters except as a matched pair at its
start and end. The pre-processing will detect some such errors; others will
only be detected if and when their substitution creates invalid source
lines.)
Notes on option naming:
* All names are case-sensitive.
* All names have been restricted to a maximum of 15 characters, partly in
order not to produce really excessive case-sensitive typing exercises, and
partly in order to keep the source formatting reasonably sane. This does
entail the use of some abbreviations.
Standard Assembly-time Options
------------------------------
The data abort veneer's source file will cater for the following
assembly-time options:
* A mandatory option specifying the symbolic name of the veneer's entry
point:
-PD 'VeneerEntry SETS "<entry_point_name>"'
A symbol of the given name will be generated and EXPORTed. It is the
responsibility of the rest of the system to ensure that the data abort
vector at 0x00000010 or 0xFFFF0010 transfers control to this entry point -
typically via code such as:
B <entry_point_name>
or:
LDR PC,DataAbortHandler
:
:
DataAbortHandler DCD <entry_point_name>
* An option to specify the name of the area created by the assembly:
-PD 'AreaName SETS "<area_name>"'
This defaults to "DataAbortVeneerCode"; the most likely reason for wanting
to change it is to affect linking order.
* Options specifying the abort model(s) supported:
-PD 'BaseUpdated SETL {TRUE}'
Support the "Base Updated Abort Model". (This is the one used in ARM6
configured for late aborts, ARM7 and ARM9, in which an aborting
instruction with base register writeback will have performed the
writeback.)
-PD 'BaseRestored SETL {TRUE}'
Support the "Base Restored Abort Model". (This is the one used in ARM8
and StrongARM, in which an aborting instruction with base register
writeback will always have left the base register unchanged.)
-PD 'EarlyAbort SETL {TRUE}'
Support the legacy "early aborts" abort model for ARM6 processors
configured for early aborts. (Note that this abort model is no longer
allowed under ARM architecture version 4, but may still be present in
older ARM-based systems. Also note that this abort model is basically a
hybrid between the other two, and thus requires almost no extra code to
support once the other two are present.)
At least one of these must be specified.
If only one abort model is specified, only the correct code for that abort
model will be assembled, and no further action by the rest of the system
is required to identify the correct abort model to use. This would be the
normal option to use in an embedded system, for which the exact processor
version being used is known and constant.
If more than one abort model is specified, the correct code for all
selected abort models is assembled, and the rest of the system is required
to communicate the correct abort model to use to the data abort veneer
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -